library(tidyverse)
library(cowplot)

********************************************************
Note: As of version 1.0.0, cowplot does not change the
  default ggplot2 theme anymore. To recover the previous
  behavior, execute:
  theme_set(theme_cowplot())
********************************************************
library(lubridate)

Attaching package: ‘lubridate’

The following object is masked from ‘package:cowplot’:

    stamp

The following objects are masked from ‘package:dplyr’:

    intersect, setdiff, union

The following objects are masked from ‘package:base’:

    date, intersect, setdiff, union
library(mgcv)
source("UVP_2017_library.R")
theme_set(theme_cowplot())
cb10 <- c('#a6cee3','#1f78b4','#b2df8a','#33a02c','#fb9a99','#e31a1c','#fdbf6f','#ff7f00','#cab2d6','#6a3d9a')

Particles Only

Read In Data

bes<- read_csv("dataOut/binned_EachSize.csv")
Parsed with column specification:
cols(
  .default = col_double(),
  project = col_character(),
  profile = col_character(),
  time = col_datetime(format = "")
)
See spec(...) for full column specifications.
bds <- read_csv("dataOut/binned_DepthSummary.csv")
Parsed with column specification:
cols(
  .default = col_double(),
  project = col_character(),
  profile = col_character(),
  time = col_datetime(format = "")
)
See spec(...) for full column specifications.
ues <- read_csv("dataOut/unbinned_EachSize.csv")
Parsed with column specification:
cols(
  project = col_character(),
  profile = col_character(),
  time = col_datetime(format = ""),
  depth = col_double(),
  psd_gam = col_double(),
  vol = col_double(),
  sizeclass = col_character(),
  lb = col_double(),
  ub = col_double(),
  binsize = col_double(),
  TotalParticles = col_double(),
  nparticles = col_double(),
  n_nparticles = col_double(),
  biovolume = col_double(),
  speed = col_double(),
  flux = col_double(),
  flux_fit = col_double(),
  GamPredictTP = col_double()
)
uds <- read_csv("dataOut/unbinned_DepthSummary.csv")
Parsed with column specification:
cols(
  .default = col_double(),
  project = col_character(),
  profile = col_character(),
  time = col_datetime(format = "")
)
See spec(...) for full column specifications.
PhoticBase <- 160
OMZBase <- 850

Summary Statistics

PlotNParticles <- uds %>% 
  ggplot(aes(x = tot_nparticles, y = depth, col = profile)) +
 facet_wrap(~project) +
 geom_point(alpha = 0.3, shape = 1) +
scale_y_reverse() + scale_x_log10()

PlotNParticles

bdsAddTime <- bds %>%
  mutate(Hour = hour(time), Day = day(time))

FSG1 <- gam(tot_nparticles~ s(depth, k = 3) + s(Day, k = 3) + s(Hour, k = 4, bs = "cc"), knots = list(Hour = c(0, 24)), data = bdsAddTime %>% filter(depth >= 175 & depth <=500 & project == "ETNP"))

FSG2 <- gam(tot_nparticles ~ s(depth, k = 3) + s(Day, k = 3), data = bdsAddTime %>% filter(depth >= 175 & depth <=500 & project == "ETNP"))

FSG3 <- gam(tot_nparticles ~ s(depth, k = 3), data = bdsAddTime %>% filter(depth >= 175 & depth <=500 & project == "ETNP"))

#FSG4 <- gam(tot_nparticles~ s(depth, k = 3)  + s(Hour, k = 4, bs = "cc"), knots = list(Hour = c(0, 24)), data = bdsAddTime %>% filter(depth >= 175 & depth <=500 & project == "ETNP"))

summary(FSG1)

Family: gaussian 
Link function: identity 

Formula:
tot_nparticles ~ s(depth, k = 3) + s(Day, k = 3) + s(Hour, k = 4, 
    bs = "cc")

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)    9.002      0.106   84.96   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
           edf Ref.df     F p-value  
s(depth) 1.204  1.366 3.346  0.0874 .
s(Day)   1.512  1.761 3.001  0.0386 *
s(Hour)  1.579  2.000 2.713  0.0389 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =  0.183   Deviance explained = 24.2%
GCV = 0.73885  Scale est. = 0.67365   n = 60
#summary(FSG2)
#summary(FSG3)
#summary(FSG4)

summary(FSG1)$r.sq - summary(FSG2)$r.sq
[1] 0.07590024
summary(FSG2)$r.sq - summary(FSG3)$r.sq
[1] 0.05267319
summary(FSG3)$r.sq
[1] 0.0542546

But there is between projects:

ProjGam <- gam(tot_nparticles~ s(depth, k = 3) + factor(project), knots = list(Hour = c(0, 24)), data = bdsAddTime %>% filter(depth >= 175 & depth <=500))

summary(ProjGam)

Family: gaussian 
Link function: identity 

Formula:
tot_nparticles ~ s(depth, k = 3) + factor(project)

Parametric coefficients:
                   Estimate Std. Error t value Pr(>|t|)    
(Intercept)          8.9983     0.4445   20.24   <2e-16 ***
factor(project)P16  17.0001     1.3754   12.36   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
         edf Ref.df     F p-value  
s(depth)   1      1 3.552   0.064 .
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =    0.7   Deviance explained = 70.9%
GCV = 12.411  Scale est. = 11.855    n = 67
library(scales)

Attaching package: ‘scales’

The following object is masked from ‘package:purrr’:

    discard

The following object is masked from ‘package:readr’:

    col_factor
#https://stackoverflow.com/questions/30179442/plotting-minor-breaks-on-a-log-scale-with-ggplot
log_breaks = function(maj, radix=10) {
  function(x) {
    minx         = floor(min(logb(x,radix), na.rm=T)) - 1
    maxx         = ceiling(max(logb(x,radix), na.rm=T)) + 1
    n_major      = maxx - minx + 1
    major_breaks = seq(minx, maxx, by=1)
    if (maj) {
      breaks = major_breaks
    } else {
      steps = logb(1:(radix-1),radix)
      breaks = rep(steps, times=n_major) +
               rep(major_breaks, each=radix-1)
    }
    radix^breaks
  }
}
scale_x_log_eng = function(..., radix=10) {
  scale_x_continuous(...,
                     trans=log_trans(radix),
                     breaks=log_breaks(TRUE, radix),
                     minor_breaks=log_breaks(FALSE, radix))
}

#theme_set(theme_bw)
PlotPSDmany <- uds %>% 
  filter(project == "ETNP") %>%
  ggplot(aes(x = psd, y = depth, shape = factor(day(time)), fill = hour(time))) +
 
  #geom_path(aes(x = psd_gam)) + 
  #geom_ribbon(aes(x = psd_gam, xmin = psd_gam - 2 * psd_seg, xmax = psd_gam + 2 * psd_seg), alpha = 0.1, outline_type = "lower") +
  geom_point(alpha = .6, size = 2, stroke = 1) +
  scale_y_reverse(limits = c(1200, 0)) + scale_shape_manual(values = c(21:25)) +
  scale_fill_gradientn(breaks = c(0, 6, 12, 18, 24), colors = c("black", "blue", "white", "orange", "black")) +
  labs(y = "Depth (m)", x = "Particle Size Distribution Slope") + 
  geom_hline(yintercept = 175, color = "darkgreen") +
  geom_hline(yintercept = 850, color = "darkblue") 

#theme_set(theme_cowplot)

PlotParticlesmany <- uds %>% 
  filter(project == "ETNP") %>%
  ggplot(aes(x = tot_nparticles, y = depth, shape = factor(day(time)), fill = hour(time))) +
 
  #geom_path(aes(x = psd_gam)) + 
  #geom_ribbon(aes(x = psd_gam, xmin = psd_gam - 2 * psd_seg, xmax = psd_gam + 2 * psd_seg), alpha = 0.1, outline_type = "lower") +
  geom_point(alpha = .6, size = 2, stroke = 1) +
  scale_y_reverse(limits = c(1200, 0)) + scale_shape_manual(values = c(21:25)) +
  scale_fill_gradientn(breaks = c(0, 6, 12, 18, 24), colors = c("black", "blue", "white", "orange", "black")) +
  scale_x_log10(breaks = c(10, 100, 1000), minor = c(5, 50, 500)) +
  #theme(legend.position = "none") +
  #scale_x_log_eng()+
  labs(y = "Depth (m)", x = "Particles / L") + 
  geom_hline(yintercept = 175, color = "darkgreen") +
  geom_hline(yintercept = 850, color = "darkblue") 

# PlotFluxmany <- uds %>% 
#   filter(project == "ETNP") %>%
#   ggplot(aes(x = tot_flux_fit, y = depth, shape = factor(day(time)), fill = hour(time))) +
#  
#   #geom_path(aes(x = psd_gam)) + 
#   #geom_ribbon(aes(x = psd_gam, xmin = psd_gam - 2 * psd_seg, xmax = psd_gam + 2 * psd_seg), alpha = 0.1, outline_type = "lower") +
#   geom_point(alpha = .6, size = 2, stroke = 1) +
#   scale_y_reverse() + scale_shape_manual(values = c(21:25)) +
#   scale_fill_gradientn(breaks = c(0, 6, 12, 18, 24), colors = c("black", "blue", "white", "orange", "black")) +
#   scale_x_log10() + theme(legend.position = "none")



plot_grid(
  PlotParticlesmany,
  PlotPSDmany,
  rel_widths = c(2, 3)
  )
Removed 266 rows containing missing values (geom_point).Removed 266 rows containing missing values (geom_point).

ggsave("figures/ParticlesPSDMany.png")
Saving 12 x 7.41 in image
ggsave("figures/ParticlesPSDMany.svg")
Saving 12 x 7.41 in image
bdsAddTime <- bds %>%
  mutate(Hour = hour(time), Day = day(time))

FSG1 <- gam(psd~ s(depth, k = 3) + s(Day, k = 3) + s(Hour, k = 4, bs = "cc"), knots = list(Hour = c(0, 24)), data = bdsAddTime %>% filter(depth >= 175 & depth <=500 & project == "ETNP"))

FSG2 <- gam(psd ~ s(depth, k = 3) + s(Day, k = 3), data = bdsAddTime %>% filter(depth >= 175 & depth <=500 & project == "ETNP"))

FSG3 <- gam(psd ~ s(depth, k = 3), data = bdsAddTime %>% filter(depth >= 175 & depth <=500 & project == "ETNP"))

FSG4 <- gam(psd~ s(depth, k = 3)  + s(Hour, k = 4, bs = "cc"), knots = list(Hour = c(0, 24)), data = bdsAddTime %>% filter(depth >= 175 & depth <=500 & project == "ETNP"))

summary(FSG1)

Family: gaussian 
Link function: identity 

Formula:
psd ~ s(depth, k = 3) + s(Day, k = 3) + s(Hour, k = 4, bs = "cc")

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) -3.96083    0.01988  -199.3   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
           edf Ref.df      F p-value    
s(depth) 1.713  1.917 56.197 5.5e-15 ***
s(Day)   1.000  1.000  1.078  0.3036    
s(Hour)  1.604  2.000  3.049  0.0285 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =  0.635   Deviance explained = 66.1%
GCV = 0.026006  Scale est. = 0.023702  n = 60
#summary(FSG2)
#summary(FSG3)
summary(FSG4)

Family: gaussian 
Link function: identity 

Formula:
psd ~ s(depth, k = 3) + s(Hour, k = 4, bs = "cc")

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) -3.96083    0.01995  -198.5   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
           edf Ref.df      F  p-value    
s(depth) 1.715  1.919 55.141 7.66e-15 ***
s(Hour)  1.565  2.000  2.497   0.0488 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =  0.632   Deviance explained = 65.2%
GCV = 0.02572  Scale est. = 0.023885  n = 60
summary(FSG1)$r.sq - summary(FSG2)$r.sq
[1] 0.03804023
summary(FSG2)$r.sq - summary(FSG3)$r.sq
[1] -0.004905911
summary(FSG3)$r.sq
[1] 0.6015425

Not a significant difference in PSD with respect to time.

But there is between projects:

ProjGam <- gam(psd~ s(depth, k = 3) + factor(project), knots = list(Hour = c(0, 24)), data = bdsAddTime %>% filter(depth >= 175 & depth <=500))

summary(ProjGam)

Family: gaussian 
Link function: identity 

Formula:
psd ~ s(depth, k = 3) + factor(project)

Parametric coefficients:
                   Estimate Std. Error  t value Pr(>|t|)    
(Intercept)        -3.96167    0.02491 -159.029   <2e-16 ***
factor(project)P16 -0.19977    0.07708   -2.592   0.0118 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
           edf Ref.df     F  p-value    
s(depth) 1.224  1.398 34.54 2.26e-08 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =  0.437   Deviance explained = 45.6%
GCV = 0.039117  Scale est. = 0.037234  n = 67

I wonder if I can show that the profiles aren’t statistically significanlty different. Or that they are for that matter… I think in that case, I run a gam with and without a parameter for profile… And then quantify the effect size of that parameter

Or follow this Gavin Simpson Post https://fromthebottomoftheheap.net/2017/10/10/difference-splines-i/

or anova.gam {mgcv}

Calculate gams for each profile, and then run anova.gam to see if they are different…

PlotNParticlesEP <- uds %>% 
  filter(profile %in% c("stn_043", "p16n_100")) %>%
  ggplot(aes(x = tot_nparticles, y = depth, col = project, shape = project)) +
 geom_point(alpha = 0.7, size = 2, stroke = 1) +
  #geom_path(aes(x = tot_nparticles)) +
  #geom_ribbon(aes(x = psd_gam, xmin = psd_gam - 2 * psd_seg, xmax = psd_gam + 2 * psd_seg), alpha = 0.1) +
scale_y_reverse(limits = c(1000, 0)) + scale_x_log10() + scale_color_manual(values = c("gray20", "brown")) +
  labs(x = "Particles/L", y = "Depth (m)") +
  theme(legend.position = "none") +
  scale_shape_manual(values = c(1:5)) +
  geom_hline(yintercept = 175, color = "darkgreen") +
  geom_hline(yintercept = 200, color = "darkgreen") +
  geom_hline(yintercept = 850, color = "darkblue") 

PlotNParticlesEP

I removed one outlyer from p16 for visualization purposes (300 particles/l at surface)

PlotPSDEP <- uds %>% 
  filter(profile %in% c("stn_043", "p16n_100")) %>%
  ggplot(aes(x = psd, y = depth, col = project, shape = project)) +
 geom_point(alpha = 0.7, size = 2, stroke = 1) +
  geom_path(aes(x = psd_gam)) +
  geom_ribbon(aes(x = psd_gam, xmin = psd_gam - 2 * psd_seg, xmax = psd_gam + 2 * psd_seg), alpha = 0.1) +
scale_y_reverse(limits = c(1000, 0)) + scale_color_manual(values = c("gray20", "brown"))  +
  scale_shape_manual(values = c(1:5)) + labs(y = "", x = "Particle Size Distribution Slope") +
  geom_hline(yintercept = 175, color = "darkgreen") +
  geom_hline(yintercept = 200, color = "darkgreen") +
  geom_hline(yintercept = 850, color = "darkblue") 

PlotPSDEP

I may just cow these togther.

plot_grid(PlotNParticlesEP, PlotPSDEP, rel_widths = c(2,3), labels = c("A", "B"))
Removed 1211 rows containing missing values (geom_point).Removed 1211 rows containing missing values (geom_point).Removed 1211 row(s) containing missing values (geom_path).

ggsave("figures/ParticlesAndPSD_ETNPVsP16.svg")
Saving 10 x 4 in image
ggsave("figures/ParticlesAndPSD_ETNPVsP16.png")
Saving 10 x 4 in image
mainParticleComponents <- bds %>%
  filter(profile %in% c("stn_043", "p16n_100")) %>%
  select(project, profile, depth,
         tot_nparticles, small_nparticles, big_nparticles,
         tot_psd = psd, small_psd, big_psd,
         tot_flux_fit, small_flux_fit, big_flux_fit) %>%
  pivot_longer(cols = -c("project", "profile", "depth")) %>%
  separate(name, c("size", "meas")) %>%
  mutate(meas = recode(meas, nparticles = "particles/L")) %>%
  mutate(meas = factor(meas, levels = c("particles/L", "flux", "psd")))
Expected 2 pieces. Additional pieces discarded in 273 rows [7, 8, 9, 16, 17, 18, 25, 26, 27, 34, 35, 36, 43, 44, 45, 52, 53, 54, 61, 62, ...].
PlotFlx <- mainParticleComponents %>% 
  filter(meas != "psd") %>%
  ggplot(aes(y = depth, x = value, col = project, shape = project)) + facet_grid(size ~ meas, scales = "free_x") + geom_point(size = 2) + scale_y_reverse(limits = c(1000, 0)) + scale_x_log10() + theme(axis.title.x = element_blank(), legend.position = "none", strip.background.y = element_blank(), strip.text.y = element_blank(), plot.margin = unit(c(7,0,7,7), "pt")) + scale_color_manual(values = c("brown", "gray20")) + scale_shape_manual(values = c(1:5)) + theme(axis.text.x = element_text(angle = 90)) + geom_hline(yintercept = 175, color = "darkgreen")

PlotPSD <- mainParticleComponents %>% 
  filter(meas == "psd") %>%
  ggplot(aes(y = depth, x = value, col = project, shape = project)) + facet_grid(size~meas, scales = "free_x") + geom_point(size = 2) + scale_y_reverse(limits = c(1000, 0)) +
  theme(axis.title.x = element_blank(), axis.title.y = element_blank(), axis.line.y = element_blank(), axis.text.y = element_blank(), axis.ticks.y = element_blank(), plot.margin = unit(c(7,7,26.5,0), "pt")) +
  scale_color_manual(values = c("brown", "gray20")) +  scale_shape_manual(values = c(1:5)) +  theme(axis.text.x = element_text(angle = 90)) + geom_hline(yintercept = 175, color = "darkgreen")

plot_grid(PlotFlx, PlotPSD, rel_widths = c(3, 2))
Removed 246 rows containing missing values (geom_point).Removed 123 rows containing missing values (geom_point).
ggsave("figures/BigVsSmall.svg")
Saving 7.29 x 4.5 in image
ggsave("figures/BigVsSmall.png")
Saving 7.29 x 4.5 in image

Flux small and flux tot track so closely because ag > psd. since the size distribution of the flux sould be PSD + ag (psd is negative in this case). Yo ucan see the variance at the one depth where psd is flatest at the very top. time 2017-01-13 17:51:31 202.4 L

eg_dataline <- bds %>% 
  filter(profile == "stn_043", depth == 162.5)
eg_slope =  eg_dataline %>% pull(psd)
eg_icp = eg_dataline %>% pull(icp)
eg_vol = eg_dataline %>% pull(vol)

eg_datablock <- bes %>%
  filter(profile == "stn_043", depth == 162.5)


eg_lb = eg_datablock$lb
eg_binsize = eg_datablock$binsize
eg_nnp = exp(eg_icp + log(eg_lb) * eg_slope)

eg_np = eg_nnp * eg_binsize
eg_tp = eg_np * eg_vol
eg_df <- tibble(lb = eg_lb, n_nparticles = eg_nnp, nparticles = eg_np, TotalParticles = eg_tp)


EgNNP <- eg_datablock %>%
  ggplot(aes(x = lb, y = n_nparticles)) + geom_point() + scale_x_log10() + scale_y_log10() + 
  geom_path(data = eg_df) + labs(y = "Binsize & Volume Normalized \n Particles (#/L/mm)", x = "Size (mm)")

EgNP <- eg_datablock %>%
  ggplot(aes(x = lb, y = nparticles)) + geom_point() + scale_x_log10() + scale_y_log10() + 
  geom_path(data = eg_df) + labs(y = "Normalized Particles" , x = "Size (mm)")

EgTP <- eg_datablock %>%
  ggplot(aes(x = lb, y = TotalParticles)) + geom_point() + scale_x_log10() + scale_y_log10() + 
  geom_path(data = eg_df) + labs( y = "Total Particles Observed (#)", x = "Size (mm)")

plot_grid(EgNNP, EgTP, labels = c("A", "B"))
Transformation introduced infinite values in continuous y-axisTransformation introduced infinite values in continuous y-axis
ggsave("figures/ExamplePSD163m.png")
Saving 7.29 x 4.5 in image
ggsave("figures/ExamplePSD163m.svg")
Saving 7.29 x 4.5 in image

Smooth flux and um disaggregation.

bds %>% 
  ggplot(aes(y = depth, x = Flux_Smooth, col = factor(time))) + facet_wrap(~project) + geom_point() + scale_y_reverse(limits = c(1000, 0)) + scale_x_log10()

bdsAddTime <- bds %>%
  mutate(Hour = hour(time), Day = day(time))

FSG1 <- gam(Flux_Smooth~ s(depth, k = 3) + s(Day, k = 3) + s(Hour, k = 4, bs = "cc"), knots = list(Hour = c(0, 24)), data = bdsAddTime %>% filter(depth >= 175 & depth <=500 & project == "ETNP"))

FSG2 <- gam(Flux_Smooth ~ s(depth, k = 3) + s(Day, k = 3), data = bdsAddTime %>% filter(depth >= 175 & depth <=500 & project == "ETNP"))

FSG3 <- gam(Flux_Smooth ~ s(depth, k = 3), data = bdsAddTime %>% filter(depth >= 175 & depth <=500 & project == "ETNP"))

summary(FSG1)

Family: gaussian 
Link function: identity 

Formula:
Flux_Smooth ~ s(depth, k = 3) + s(Day, k = 3) + s(Hour, k = 4, 
    bs = "cc")

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  34.7319     0.9334   37.21   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
           edf Ref.df      F  p-value    
s(depth) 1.875  1.984 11.823 0.000126 ***
s(Day)   1.756  1.939  2.168 0.094012 .  
s(Hour)  1.114  2.000  1.658 0.059271 .  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =   0.33   Deviance explained = 38.4%
GCV = 57.811  Scale est. = 52.277    n = 60
summary(FSG2)

Family: gaussian 
Link function: identity 

Formula:
Flux_Smooth ~ s(depth, k = 3) + s(Day, k = 3)

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  34.7319     0.9607   36.15   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
           edf Ref.df      F  p-value    
s(depth) 1.869  1.983 11.102 0.000206 ***
s(Day)   1.811  1.964  2.743 0.094614 .  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =   0.29   Deviance explained = 33.4%
GCV = 60.062  Scale est. = 55.377    n = 60
summary(FSG3)

Family: gaussian 
Link function: identity 

Formula:
Flux_Smooth ~ s(depth, k = 3)

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  34.7319     0.9944   34.93   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
           edf Ref.df     F  p-value    
s(depth) 1.857  1.979 10.73 0.000277 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =  0.239   Deviance explained = 26.3%
GCV = 62.291  Scale est. = 59.325    n = 60
summary(FSG1)$r.sq - summary(FSG2)$r.sq
[1] 0.03975922
summary(FSG2)$r.sq - summary(FSG3)$r.sq
[1] 0.05063133
summary(FSG3)$r.sq
[1] 0.2392424
bds %>% filter(project == "ETNP") %>% select(profile, depth, Flux_Smooth) %>% pivot_wider(names_from = profile, values_from = Flux_Smooth)

Something is off. All of the flux profiles are identical. Skip this

cb10 <- c('#a6cee3','#1f78b4','#b2df8a','#33a02c','#fb9a99','#e31a1c','#fdbf6f','#ff7f00','#cab2d6','#6a3d9a')
plt1 <- bds %>% #filter(DFP > 1) %>% #filter(profile %in% c("stn_043", "p16n_100")) %>%
  ggplot(aes(y = depth, x = DFP, col = factor(time), shape = factor(time))) + facet_wrap(~project) + geom_point() + scale_y_reverse(limits = c(1000, 0)) + xlim(c(0.5, 1.5))+ geom_vline(xintercept = 1) +
   scale_color_manual(values = c(rep("black", 5), rep("blue", 5))) + scale_shape_manual(values = rep(1:5, 2))

plotly::ggplotly(plt1)
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio

What the heck is going on with DFP here. Why is it usually > 1 shouldn’t it be less than 1 when flux is decreasing? This very deep increasing flux seems improbable to me. Lets check the smooths. Or only go to 1000m.

, legend.background = element_blank(), legend.box.background = element_rect()

scientific_10 <- function(x) {parse(text=gsub("e\\+*", " %*% 10^", scales::scientific_format()(x))) }
scientific_10_b <- function(x) {parse(text=gsub("e\\+*", " %*% 10^", scales::scientific_format()(x))) }

scientific_10_c <- function(x) {
    xout <- gsub("1e", "10^{", format(x),fixed=TRUE)
    xout <- gsub("{-0", "{-", xout,fixed=TRUE)
    xout <- gsub("{+", "{", xout,fixed=TRUE)
    xout <- gsub("{0", "{", xout,fixed=TRUE)
    xout <- paste(xout,"}",sep="")
    return(parse(text=xout))
    
}

scale_x_log10nice <- function(name=NULL,omag=seq(-10,20),...) {
    breaks10 <- 10^omag
    scale_x_log10(breaks=breaks10,labels=scientific_10_c(breaks10),...)
}


#https://stackoverflow.com/questions/10762287/how-can-i-format-axis-labels-with-exponents-with-ggplot2-and-scales
#jacob_magnitude <- function(x){expression(10^round(log10(x)))}

cb10 <- c('#a6cee3','#1f78b4','#b2df8a','#33a02c','#fb9a99','#e31a1c','#fdbf6f','#ff7f00','#cab2d6','#6a3d9a')
pltFlx <- bds %>% filter(project == "ETNP") %>% #filter(DFP > 1) %>% #filter(profile %in% c("stn_043", "p16n_100")) %>%
  ggplot(aes(y = depth, x = Flux_Smooth, shape = factor(day(time)), fill = hour(time), group = factor(time)))  + geom_point(size = 2, stroke = 1)+
  #geom_path() +
  scale_y_reverse(limits = c(1000, 0))+
  scale_x_log10nice()+
  #scale_x_log10() + 
   scale_color_gradient2(low = "darkgreen", mid = "gray80", high = "purple", midpoint = 10) + scale_shape_manual(name = "Day of Month", values = rep(21:25, 2)) + 
  scale_fill_gradientn(name = "Hour of Day", breaks = c(0, 6, 12, 18, 24), colors = c("black", "blue", "white", "orange", "black")) +
  
  labs(x = bquote(Smoothed~Flux~(µmol~C/m^2/d)), y = "Depth (m)") +
  #labs(x = "moo", y = "Depth (m)") +
  geom_rect(data = data.frame(project = "ETNP"), aes(xmin = 20, xmax = 180, ymin = 75, ymax = 500), colour = "red", fill = NA, inherit.aes = FALSE) +
  theme(axis.text.x = element_text(angle = 90, vjust = .3), legend.spacing = unit(.1, "cm")) +
   geom_segment(aes(y = 160, yend = 160, x = 20, xend = 500), color = "darkgreen", stroke = 0.5)+
   geom_segment(aes(y = 850, yend = 850, x = 20, xend = 500), color = "darkblue", stroke = 0.5)#+ geom_hline(yintercept = 850, color = "darkblue")
Ignoring unknown parameters: strokeIgnoring unknown parameters: stroke
pltFlxNoLegend <- pltFlx + theme(legend.position = "none")
pltFlxLegend <- get_legend(pltFlx)
Removed 14 rows containing missing values (geom_point).
pltFlx

#plotly::ggplotly(plt1)
cb10 <- c('#a6cee3','#1f78b4','#b2df8a','#33a02c','#fb9a99','#e31a1c','#fdbf6f','#ff7f00','#cab2d6','#6a3d9a')
pltFlxZoom <- bds %>% filter(project == "ETNP" & depth <= 500 & depth >= 75) %>% #filter(profile %in% c("stn_043", "p16n_100")) %>%
  ggplot(aes(y = depth, x = Flux_Smooth, shape = factor(day(time)), fill = hour(time), group = factor(time))) + geom_point(size = 2, stroke = 1)+
  #geom_path() +
  scale_y_reverse()+
  #scale_x_log10() +
  scale_x_log10(breaks = c(seq(from = 20, to = 50, by = 10), seq(from = 60, to = 180, by = 20)), limits = c(20, 180)) +
   scale_color_gradient2(low = "darkgreen", mid = "gray80", high = "purple", midpoint = 10) + scale_shape_manual(values = rep(21:25, 2)) + 
  scale_fill_gradientn(breaks = c(0, 6, 12, 18, 24), colors = c("black", "blue", "white", "orange", "black")) +
  theme(axis.text.x = element_text(angle = 90)) +
labs(x = "Smoothed Flux", y = "Depth") + theme(legend.position = "none")+
geom_hline(yintercept = 160, color = "darkgreen")

pltFlxZoom

#plotly::ggplotly(plt1)
cb10 <- c('#a6cee3','#1f78b4','#b2df8a','#33a02c','#fb9a99','#e31a1c','#fdbf6f','#ff7f00','#cab2d6','#6a3d9a')
pltDelta3 <- bds %>% filter(project == "ETNP") %>% #filter(DFP > 1) %>% #filter(profile %in% c("stn_043", "p16n_100")) %>%
  ggplot(aes(y = depth, x = pracma::nthroot(DF/DZ, 5), shape = factor(day(time)), fill = hour(time), group = factor(time)))  + geom_point(size = 2, stroke = 1)+
  #geom_path() +
  scale_y_reverse(limits = c(1000, 0))+
  scale_x_continuous(limits = c(-2.1, .6), breaks = seq(from = -2, to = .75, by = 0.5)) +
  #scale_x_log10() +
   scale_color_gradient2(low = "darkgreen", mid = "gray80", high = "purple", midpoint = 10) + scale_shape_manual(name = "Day of Month", values = rep(21:25, 2)) + 
  scale_fill_gradientn(name = "Hour", breaks = c(0, 6, 12, 18, 24), colors = c("black", "blue", "white", "orange", "black")) +
  geom_vline(xintercept = 0) +
  labs(x = bquote((DF/DZ)^{1/5}~(µmolC/m^3/d)^{1/5}), y = "Depth (m)") + theme(legend.pos = "none")+
  geom_hline(yintercept = 160, color = "darkgreen") + geom_hline(yintercept = 850, color = "darkblue")
  #labs(x = "(DF/DZ) ^ 1/5 (µmol C/m^3/d) ^ 1/5")

pltDelta3

#plotly::ggplotly(plt1pos)
# #plot_grid(pltFlxNoLegend, pltFlxZoom, pltDelta3, pltFlxLegend)
# 
# pltFlxLegend <- get_legend(pltFlx + theme(legend.box.margin = margin(0, 0, 40, 10)))
# 
# pgTop <- plot_grid(pltFlxNoLegend, pltFlxZoom + theme(plot.margin = unit(c(1, 0, 3, 0), units = "cm")), rel_widths = c(2, 1), labels = c("A", "B"))
# pgBottom <- plot_grid(pltDelta3, pltFlxLegend , rel_widths = c(3, 1), labels = c("C", ""), label_size = 14)
# pgBoth <- plot_grid(pgTop, pgBottom, ncol = 1)
# 
# pgBoth
# 
# ggsave("figures/FluxDeepDive.png")
# ggsave("figures/FluxDeepDive.svg")

Within panel drawing

pgTop <- ggdraw(pltFlxNoLegend 
       ) +
  draw_plot(pltFlxZoom, .4, .25, .55, .60) +
  draw_plot_label(
    c("","B"),
    c(.05, 0.55),
    c(1, 0.85),
    size = 16
  )
Removed 14 rows containing missing values (geom_point).
pgTop

pgBottom <- plot_grid(pltDelta3, pltFlxLegend , rel_widths = c(3, 1), labels = c(“C”, ""), label_size = 14)

I don’t know whats going on below here

pgBottom <- pltDelta3  + geom_rect(aes(xmin = -2, xmax = -1.15, ymin = 170, ymax = 1000), colour = "gray50", fill = NA, inherit.aes = FALSE) + draw_plot(pltFlxLegend , -1.9, -575, .7)
pgBoth <- plot_grid(pgTop + theme(plot.margin = unit(c(0, 0, 0, 0), units = "cm")),
                    pgBottom + theme(plot.margin = unit(c(0, 0, 0, 0), units = "cm")),
                    ncol = 1, rel_heights = c(4, 4), labels = c("A", "C"), label_size = 16)
Removed 33 rows containing missing values (geom_point).
pgBoth


ggsave("figures/FluxDeepDive.png")
Saving 5 x 9 in image
ggsave("figures/FluxDeepDive.svg")
Saving 5 x 9 in image
# #plot_grid(pltFlxNoLegend, pltFlxZoom, pltDelta3, pltFlxLegend)
# 
# pltFlxLegend <- get_legend(pltFlx + theme(legend.box.margin = margin(0, 0, 40, 10)))
# 
# pgTop <- plot_grid(pltFlxNoLegend + ylim(c(1000, 0)), pltFlxZoom + theme(plot.margin = unit(c(1, 0, 3, 0), units = "cm")), rel_widths = c(2, 1), labels = c("A", "B"))
# pgBottom <- plot_grid(pltDelta3 + ylim(c(1000, 0)), pltFlxLegend , rel_widths = c(3, 1), labels = c("C", ""))
# pgBoth <- plot_grid(pgTop, pgBottom, ncol = 1)
# 
# pgBoth
# 
# #ggsave("figures/FluxShallowDive.png")
# #ggsave("figures/FluxShallowDive.svg")

Test for day to day and hourly variability in delta flux

bdsAddTime <- bds %>% 
  mutate(Hour = hour(time), Day = day(time))

DFG1 <- gam(pracma::nthroot(DF/DZ, 5)~ s(depth, k = 3) + s(Day, k = 3) + s(Hour, k = 4, bs = "cc"), knots = list(Hour = c(0, 24)), data = bdsAddTime %>% filter(depth >= 250 & depth <=500 & project == "ETNP"))

DFG2 <- gam(pracma::nthroot(DF/DZ, 5) ~ s(depth, k = 3) + s(Day, k = 3), data = bdsAddTime %>% filter(depth >= 250 & depth <=500 & project == "ETNP"))

DFG3 <- gam(pracma::nthroot(DF/DZ, 5) ~ s(depth, k = 3), data = bdsAddTime %>% filter(depth >= 250 & depth <=500 & project == "ETNP"))

summary(DFG1)

Family: gaussian 
Link function: identity 

Formula:
pracma::nthroot(DF/DZ, 5) ~ s(depth, k = 3) + s(Day, k = 3) + 
    s(Hour, k = 4, bs = "cc")

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)   
(Intercept) -0.18385    0.05564  -3.305  0.00217 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
           edf Ref.df     F p-value   
s(depth) 1.722  1.922 4.549 0.03760 * 
s(Day)   1.943  1.997 8.215 0.00139 **
s(Hour)  1.470  2.000 2.587 0.04015 * 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =  0.359   Deviance explained = 43.9%
GCV = 0.15225  Scale est. = 0.13001   n = 42
summary(DFG2)

Family: gaussian 
Link function: identity 

Formula:
pracma::nthroot(DF/DZ, 5) ~ s(depth, k = 3) + s(Day, k = 3)

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)   
(Intercept) -0.18385    0.05943  -3.094  0.00373 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
           edf Ref.df     F p-value   
s(depth) 1.661  1.885 3.673 0.07425 . 
s(Day)   1.910  1.992 5.174 0.00943 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =  0.268   Deviance explained = 33.2%
GCV = 0.16645  Scale est. = 0.14833   n = 42
summary(DFG3)

Family: gaussian 
Link function: identity 

Formula:
pracma::nthroot(DF/DZ, 5) ~ s(depth, k = 3)

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)   
(Intercept) -0.18385    0.06635  -2.771  0.00849 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
           edf Ref.df     F p-value
s(depth) 1.592  1.834 3.213   0.107

R-sq.(adj) =  0.0878   Deviance explained = 12.3%
GCV = 0.19707  Scale est. = 0.18491   n = 42
summary(DFG1)$r.sq - summary(DFG2)$r.sq
[1] 0.09038471
summary(DFG2)$r.sq - summary(DFG3)$r.sq
[1] 0.1804172
summary(DFG3)$r.sq
[1] 0.08782536

png(filename = “./figures/CombinedP2Info.png”, width = 10, height = 8, units = “in”, res = 200) StationInfoPlot() dev.off()

#plot.new()
FluxGamPlot <- function(){
  par(mfrow = c(2,2))
  plot(DFG1)
  mtext(expression(bold("C")), side = 3, line = 0, adj = 0, cex = 2)
  par(mfg = c(1,1))
  mtext(expression(bold("A")), side = 3, line = 0, adj = 0, cex = 2)
  par(mfg = c(1,2))
  mtext(expression(bold("B")), side = 3, line = 0, adj = 0, cex = 2)
}

FluxGamPlot()

png(filename = "./figures/FluxGamPlot.png", width = 10, height = 8, units = "in", res = 200)
FluxGamPlot()
dev.off()
png 
  2 

Check of actual data for hour

ggplot(data = bds %>% filter(depth >= 175, depth <= 500), aes(y = DF/DZ, x = hour(time), col = depth, group = depth)) + geom_point() + geom_line()

#Osps

(u mol C / m^3 / day)

disagFig <- bds %>% filter(project == "ETNP") %>%
  ggplot(aes(y = depth, x = pracma::nthroot(ospsDZ, 3), shape = factor(day(time)), fill = hour(time), group = factor(time))) + geom_point(size = 2) + scale_y_reverse(limits = c(1000, 0)) +
  scale_x_continuous(limits = c(-1, 1)) +
  geom_vline(xintercept = 0) +   scale_shape_manual(name = "Day of Month", values = rep(21:25, 2)) +
  #labs(x = bquote("Observed - Modeled Small Particle Flux"~(μmol/m^3/day)), y = "Depth (m)") +
  labs(x = paste("Deviation from Model", expression((μmol/m^3/day)))) +
  scale_fill_gradientn(name = "Hour of Day", breaks = c(0, 6, 12, 18, 24), colors = c("black", "blue", "white", "orange", "black")) + geom_hline(yintercept = 175, color = "darkgreen") + geom_hline(yintercept = 850, color = "darkblue")
disagFig

#ggsave("..figures/FluxSizeShift.svg"

 ggsave("figures/FluxSizeShift.png")
Saving 6 x 4 in image
 ggsave("figures/FluxSizeShift.svg")
Saving 6 x 4 in image

Clara Fig

For NSF Proposal plot_grid( PlotParticlesmany, PlotPSDmany, rel_widths = c(2, 3) )


pgTop <- ggdraw(pltFlxNoLegend 
       ) +
  draw_plot(pltFlxZoom, .4, .25, .55, .60) +
  draw_plot_label(
    c("","D"),
    c(.05, 0.55),
    c(1, 0.85),
    size = 16
  )
Removed 14 rows containing missing values (geom_point).
pgCF <- plot_grid(PlotParticlesmany + ylim(c(1000, 0)),
                  PlotPSDmany + ylim(c(1000, 0)) +theme(legend.position = "none"),
                  pgTop + theme(plot.margin = unit(c(0, 0, 0, 0), units = "cm")),
                    disagFig + theme(plot.margin = unit(c(0, 0, .2, 0), units = "cm")),
                    ncol = 2, rel_heights = c(4, 4), labels = c("A", "B", "C", "E"), label_size = 16)
Scale for 'y' is already present. Adding another scale for 'y', which will replace the existing scale.
Scale for 'y' is already present. Adding another scale for 'y', which will replace the existing scale.
Removed 308 rows containing missing values (geom_point).Removed 308 rows containing missing values (geom_point).Removed 41 rows containing missing values (geom_point).
pgCF


ggsave("./figures/UVP_for_zoop_proposal.png", pgCF, width = 10, height = 8, units = "in")
bdsAddTime <- bds %>%
  mutate(Hour = hour(time), Day = day(time))

OZG1 <- gam(ospsDZ ~ s(depth, k = 3) + s(Day, k = 3) + s(Hour, k = 4, bs = "cc"), knots = list(Hour = c(0, 24)), data = bdsAddTime %>% filter(depth >= 175 & depth <=500 & project == "ETNP"))

OZG2 <- gam(ospsDZ ~ s(depth, k = 3) + s(Day, k = 3), data = bdsAddTime %>% filter(depth >= 175 & depth <=500 & project == "ETNP"))

OZG3 <- gam(ospsDZ ~ s(depth, k = 3), data = bdsAddTime %>% filter(depth >= 175 & depth <=500 & project == "ETNP"))

summary(OZG1)

Family: gaussian 
Link function: identity 

Formula:
ospsDZ ~ s(depth, k = 3) + s(Day, k = 3) + s(Hour, k = 4, bs = "cc")

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 0.066685   0.009465   7.046 3.43e-09 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
           edf Ref.df      F  p-value    
s(depth) 1.681  1.898 16.665 1.66e-05 ***
s(Day)   1.870  1.982  7.601 0.000825 ***
s(Hour)  1.319  2.000  2.124 0.047647 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =   0.45   Deviance explained = 49.6%
GCV = 0.0059577  Scale est. = 0.0053749  n = 60
summary(OZG2)

Family: gaussian 
Link function: identity 

Formula:
ospsDZ ~ s(depth, k = 3) + s(Day, k = 3)

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 0.066685   0.009813   6.796 7.85e-09 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
           edf Ref.df      F  p-value    
s(depth) 1.644  1.873 16.338 2.28e-05 ***
s(Day)   1.904  1.991  7.155  0.00258 ** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =  0.409   Deviance explained = 44.5%
GCV = 0.0062509  Scale est. = 0.0057771  n = 60
summary(OZG3)

Family: gaussian 
Link function: identity 

Formula:
ospsDZ ~ s(depth, k = 3)

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  0.06669    0.01084   6.154 7.82e-08 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
           edf Ref.df     F  p-value    
s(depth) 1.547  1.794 14.83 7.66e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =  0.279   Deviance explained = 29.8%
GCV = 0.0073573  Scale est. = 0.007045  n = 60
summary(OZG1)$r.sq - summary(OZG2)$r.sq
[1] 0.04114558
summary(OZG2)$r.sq - summary(OZG3)$r.sq
[1] 0.1296981
summary(OZG3)$r.sq
[1] 0.2793194
OSMSGamPlot <- function(){
  par(mfrow = c(1,2))
  plot(OZG2)
  mtext(expression(bold("B")), side = 3, line = 0, adj = 0, cex = 2)
  par(mfg = c(1,1))
  mtext(expression(bold("A")), side = 3, line = 0, adj = 0, cex = 2)
}

OSMSGamPlot()

png(filename = "./figures/OSMSGamPlot.png", width = 10, height = 6, units = "in", res = 200)
OSMSGamPlot()

dev.off()
png 
  2 

plot(OZG2)

bds %>% filter(project == "P16") %>%
  ggplot(aes(y = depth, x = ospsDZ)) + facet_wrap(~project) + geom_point() + scale_y_reverse(limits = c(500, 0)) + geom_vline(xintercept = 0)

Trap data

trapFlux3 <- read_csv("dataOut/fluxMS_distilled.csv")
Parsed with column specification:
cols(
  Class = col_character(),
  Depth = col_double(),
  TrapID = col_character(),
  TrapType = col_character(),
  SampleType = col_character(),
  C_flux = col_double(),
  C_flux_umol = col_double()
)
UVPFluxComb <- read_csv("dataOut/CombinedProfileFluxEst_DS.csv")
Parsed with column specification:
cols(
  depth = col_double(),
  Flux = col_double()
)
UVPFluxOE <- read_csv("dataOut/ObservedVsExpectedFlux.csv")
Parsed with column specification:
cols(
  depth = col_double(),
  tn_flux = col_double(),
  profile = col_character(),
  project = col_character(),
  time = col_character(),
  tot_flux2 = col_double()
)
trapFlux3
UVPFluxComb

fluxMS_distilled_toPlot <- trapFlux3 %>%
  mutate(SampleType = recode(SampleType, `plus.p` = "plus-particles", top = "top-collector"))

Remove traps where mass spec didn’t work correctly 2-17 150 1-12 73m 1-12 148 2-14 100 |(TrapID == “2-17” & Depth == 150)

fluxMS_distilled_toPlot2 <- fluxMS_distilled_toPlot %>%
 filter(!((TrapID == "1-12") | (TrapID == "2-14" & Depth == 100)|(TrapID == "2-17" & Depth == 150)))
fluxMS_distilled_toPlot2
# UVPFluxComb %>%
#   ggplot(aes(y = depth))  + scale_y_reverse(limits = c(1000, 0)) +
#   scale_x_continuous(limits = c(0, 200)) +
#   geom_point(aes(y = Depth, x = C_flux_umol, fill = SampleType, shape = TrapType),
#              colour = "black", stroke = 1, size = 5, data = fluxMS_distilled_toPlot) +
#   geom_point(aes(x = Flux), size = 3, shape = 21, color = "white", fill = "black") +
#   geom_point(aes(x = -1, y = -1, size = "UVP")) + # dummy point for the legend
# scale_shape_manual(values = c(25, 22))+
#   scale_size_manual(values = 1, name = "") +
#   ylab("Depth (m)") + xlab("Flux µmolC/m^2/day") +
#   guides(fill = guide_legend(override.aes = list(shape = 21))) +
#   scale_fill_viridis_d() +
#   theme_cowplot() + 
#   theme(
#         legend.position = c(0.5, 0.4),
#         legend.box.background = element_rect(color = "black", size = 0.5),
#         legend.margin = margin(-10, 5, 10, 5)
#   ) +
#   geom_rect(data = data.frame(project = "ETNP"), aes(xmin = 15, xmax = 32, ymin = 45, ymax = 195), colour = "red", fill = NA, inherit.aes = FALSE)
#  ggsave("figures/FittedFlux.png")
#  ggsave("figures/FittedFlux.svg")

Traps where mass spec didn’t work.

UVPFluxPlot00 <- UVPFluxComb %>% 
  ggplot(aes(y = depth))  + scale_y_reverse(limits = c(1000, 0)) +
  scale_x_continuous(limits = c(0, 200)) +
  geom_point(aes(y = Depth, x = C_flux_umol, shape = TrapType, ID = TrapID),
             colour = "black", stroke = 1, size = 5, data = fluxMS_distilled_toPlot2) +
  geom_line(aes(x = Flux), size = 1, color = "black") +
  geom_point(aes(x = -1, y = -1, size = "UVP Estimate")) + # dummy point for the legend
  geom_point(aes(x = tot_flux2), size = 3, shape = 21, color = "white", fill = "black", data = UVPFluxOE) +
scale_shape_manual(values = c(25, 22))+
  scale_size_manual(values = 1, name = "") +
  ylab("Depth (m)") +
  #xlab(expression(Flux µmolC/m^2/day)) +
  xlab(expression(paste("x axis ", ring(A)^2))) +
  xlab(expression(paste("Flux (µ mol C/", m^2, "/day)"))) +
  
  guides(fill = guide_legend(override.aes = list(shape = 21))) +
  theme_cowplot() + 
  theme(
        legend.position = c(0.5, 0.4),
        legend.box.background = element_rect(color = "black", size = 0.5),
        legend.margin = margin(-10, 5, 10, 5)
  ) 
Ignoring unknown aesthetics: ID
# UVPFluxPlot <- UVPFluxPlot00 +
#   geom_rect(data = data.frame(project = "ETNP"), aes(xmin = 15, xmax = 32, ymin = 45, ymax = 195), colour = "red", fill = NA, inherit.aes = FALSE)

UVPFluxPlot00

ggsave("figures/FittedFlux.png")
Saving 7.29 x 4.5 in image
ggsave("figures/FittedFlux.svg")
Saving 7.29 x 4.5 in image

Example particle size distribution

horizontalGamPlot <- dataGamHorizontal %>% ggplot(aes(x = resp_fit, y = depth, col = log(lb), group = lb)) + scale_y_reverse() + geom_point() + scale_x_log10(limits = c(10^-8, NA)) + scale_color_viridis_c() + geom_path() + geom_vline(xintercept = 1) + geom_vline(xintercept = 5) + geom_errorbar(aes(xmin = resp_lower, xmax = resp_upper), width = 10, alpha = 0.5)+ theme_bw()

TPPlot <- bes %>% filter(profile == "stn_043") %>% group_by(lb) %>% ggplot(aes(x = TotalParticles, y = depth, col = log(lb), group = lb)) + scale_y_reverse(limits = c(1000, 0)) + geom_point() + scale_x_log10() + scale_color_viridis_c() + geom_path() + geom_vline(xintercept = 1) + geom_vline(xintercept = 5) + labs(y = "Depth (m)", x = "TotalParticles Observed (#)")

nnpPlot <- bes %>% filter(profile == "stn_043") %>% group_by(lb) %>% ggplot(aes(x = n_nparticles, y = depth, col = log(lb), group = lb)) + scale_y_reverse(limits = c(1000, 0)) + geom_point() + scale_x_log10() + scale_color_viridis_c() + geom_path() + geom_vline(xintercept = 1) + geom_vline(xintercept = 5) + labs(y = "Depth (m)", x = "Binsize and Volume Normalized Particles (#/L/mm)")

FitPlot <- bes %>% filter(profile == "stn_043") %>% group_by(lb) %>% ggplot(aes(x = nnp_smooth, xmin = nnp_lower, xmax = nnp_upper, y = depth, col = log(lb), group = lb)) + scale_y_reverse(limits = c(1000, 0)) + geom_point() + scale_x_log10() + scale_color_viridis_c() + geom_path() + geom_vline(xintercept = 1) + geom_vline(xintercept = 5) + labs(y = "Depth (m)", x = "Smoothed - Normalized Particles (#/L/mm)") + geom_errorbar(width = 10, alpha = 0.5)

npLegend <- get_legend(FitPlot + theme(legend.box.margin = margin(0, 0, 40, 200)) + labs(col = expression(log[e](Size (mm)))))
Removed 325 rows containing missing values (geom_point).Removed 325 row(s) containing missing values (geom_path).
plot_grid(
  TPPlot + theme(legend.position = "none"),
  nnpPlot + theme(legend.position = "none"),
  npLegend ,
  FitPlot + theme(legend.position = "none")
)
Transformation introduced infinite values in continuous x-axisTransformation introduced infinite values in continuous x-axisRemoved 325 rows containing missing values (geom_point).Removed 325 row(s) containing missing values (geom_path).Transformation introduced infinite values in continuous x-axisTransformation introduced infinite values in continuous x-axisRemoved 325 rows containing missing values (geom_point).Removed 325 row(s) containing missing values (geom_path).Removed 325 rows containing missing values (geom_point).Removed 325 row(s) containing missing values (geom_path).

ggsave("figures/AllParticleSizes.svg")
Saving 10 x 6.18 in image
ggsave("figures/AllParticleSizes.png")
Saving 10 x 6.18 in image

Weber Bianchi Figs

SameGam <- gam(TotalParticles ~s(log(lb), log(depth), by = factor(time)), offset = log(vol * binsize), family = nb(),
    data = bes %>% filter(project == "ETNP"))
besE <- bes %>% filter(project == "ETNP")

lb_new <- exp(seq(from = log(0.1), to = log(2.1), by = 0.05))
ub_new <- lead(lb_new)
binsize_new <- ub_new - lb_new

lbbs <- tibble(lb = lb_new, ub = ub_new, binsize = binsize_new)

Expanded <- expand_grid(lb = exp(seq(from = log(0.1), to = log(2), by = 0.05)), depth = seq(from = 20, to = 2000, by = 20), time = as.factor(unique(besE$time))) %>% left_join(lbbs, by = "lb")

Pred <- exp(predict(SameGam, Expanded))
ToPlot <- bind_cols(Expanded, nnparticles = Pred) %>% mutate(time = as.character(time)) %>% mutate(nparticles = nnparticles * binsize)
ToPlot %>% filter(lb <= 2) %>%  ggplot(aes(x = lb, y = depth, fill = log10(nnparticles), z = log10(nnparticles))) + geom_tile() + scale_fill_viridis_c() + scale_y_reverse() + scale_x_log10()  + facet_wrap(~time) + geom_contour(color = "black")

meanBese <- ToPlot %>% filter(lb <= 2) %>% group_by(lb, depth) %>% summarize(nparticles = mean(nparticles), nnparticles = mean(nnparticles))

WBColorMap <- meanBese%>%
   ggplot(aes(x = lb, y = depth, fill = log10(nnparticles), z = log10(nnparticles))) + geom_tile() + scale_fill_viridis_c(name = "log10(number density \n (normalized))") + scale_y_reverse() + scale_x_log10() + geom_contour(color = "black") + geom_hline(yintercept = 160, color = "darkgreen") + geom_hline(yintercept = 850, color = "darkblue")
WBColorMap

Average of everything

#meanBese043 <- ToPlot %>% filter(lb <= 2, time == "2017-01-13 11:51:31")

meanBese%>%
   ggplot(aes(x = lb, y = depth, fill = log10(nnparticles), z = log10(nnparticles))) + geom_tile() + scale_fill_viridis_c() + scale_y_reverse() + scale_x_log10() + geom_contour(color = "black") + geom_hline(yintercept = 160, color = "darkgreen")

Just 043

mbGam <- meanBese %>% group_by(depth)  %>% nest() %>%
  mutate(mod = map(data, ~gam(log(nnparticles) ~ log(lb), family = gaussian(), data = .))) %>% 
  mutate(psd = map_dbl(mod, ~summary(.)$p.coeff[2]))
mbGam %>% ggplot(aes(x = psd, y = depth)) + geom_path() + scale_y_reverse() + geom_hline(yintercept = 160, color = "darkgreen") + geom_hline(yintercept =  850, color = "darkblue")

mbGam <- meanBese043 %>% group_by(depth) %>% nest() %>% mutate(mod = map(data, ~gam(log(nnparticles) ~ log(lb), family = gaussian(), data = .))) %>% mutate(psd = map_dbl(mod, ~summary(.)$p.coeff[2]))

pWBPSD <- mbGam %>% ggplot(aes(x = psd, y = depth)) + geom_path() + scale_y_reverse()  + geom_hline(yintercept = 160, color = "darkgreen") + geom_hline(yintercept =  850, color = "darkblue")
pWBPSD

Fig 5 WB

bds %>% filter(profile == “stn_043”, depth <= 2000) %>% ggplot(aes(x = psd_gam, xmin = psd_gam - psd_seg * 2, xmax = psd_gam + psd_seg * 2, y = depth)) + geom_path(size = 1) + scale_y_reverse() + geom_hline(yintercept = 175, color = “darkgreen”) + geom_hline(yintercept = 950, color = “darkblue”) + geom_ribbon(alpha = 0.2) + labs(x = “PSD slope”)

All of them

bds %>% filter(profile == "stn_043", depth <= 2000) %>% ggplot(aes(x = psd_gam, xmin = psd_gam - psd_seg * 2, xmax = psd_gam + psd_seg * 2, y = depth)) + geom_path(size = 1) + scale_y_reverse() + geom_hline(yintercept = 175, color = "darkgreen") + geom_hline(yintercept = 950, color = "darkblue") + geom_ribbon(alpha = 0.2) + labs(x = "PSD slope")

043 only

bds %>% filter(profile == "stn_043", depth <= 2000, depth > 175) %>% ggplot(aes(x = small_biovolume, y = depth)) + geom_path(size = 1) + scale_y_reverse() + geom_hline(yintercept = 175, color = "darkgreen") + geom_hline(yintercept = 950, color = "darkblue") + geom_point()

ubDf0 <- ToPlot %>% mutate(ubiomass = nparticles * lb ^ ag_global)
ubDf <- ubDf0 %>% group_by(time, depth) %>% summarize(ubiomass = sum(ubiomass)) %>% ungroup %>% group_by(depth)
photicBiomass <- ubDf %>% filter(depth <= 180, depth >= 160) %>% summarize(ubiomass = mean(ubiomass)) %>% pull(ubiomass)
ubDf <- ubDf %>% mutate(nbiomass = ubiomass/photicBiomass)
longer object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object length
ubDf %>% ggplot(aes(x = nbiomass, y = depth , group = time, col = time)) + geom_path() + scale_y_reverse() + scale_x_continuous(limits = c(0,1))

ubDf <- ToPlot %>% mutate(ubiomass = nparticles * lb ^ ag_global) %>% group_by(time, depth) %>% summarize(ubiomass = sum(ubiomass)) %>% ungroup %>% group_by(depth)  %>% summarise(ubiomass = mean(ubiomass))
photicBiomass <- ubDf %>% filter(depth <= 180, depth >= 160) %>% summarize(ubiomass = mean(ubiomass)) %>% pull(ubiomass)
ubDf <- ubDf %>% mutate(nbiomass = ubiomass/photicBiomass)
ubDf %>% ggplot(aes(x = nbiomass, y = depth)) + geom_path() + scale_y_reverse() + scale_x_continuous(limits = c(0,1)) + geom_hline(yintercept = 175, color = "darkgreen")

Small particles biomass

PubDf <- ToPlot %>% mutate(ubiomass = nparticles * lb ^ ag_global) %>% filter(lb < 0.5) %>% group_by(time, depth) %>% summarize(ubiomass = sum(ubiomass)) %>% ungroup %>% group_by(depth)  %>% summarise(ubiomass = mean(ubiomass))
photicBiomass <- PubDf %>% filter(depth <= 165, depth >= 155) %>% summarize(ubiomass = mean(ubiomass)) %>% pull(ubiomass)
PubDf <- PubDf %>% mutate(nbiomass = ubiomass/photicBiomass)
pWBS <- PubDf %>% ggplot(aes(x = nbiomass, y = depth)) + geom_path() + scale_y_reverse() + scale_x_continuous(limits = c(0,1.2)) + geom_hline(yintercept = 160, color = "darkgreen") + geom_vline(xintercept = 1, color = "gray50") + geom_vline(xintercept = 0, color = "gray50") + geom_hline(yintercept = 850, color = "darkblue") + labs( x = "Small particle mass (norm.)")
pWBS

LubDf <- ToPlot %>% mutate(ubiomass = nparticles * lb ^ ag_global) %>% filter(lb >= 0.5) %>% group_by(time, depth) %>% summarize(ubiomass = sum(ubiomass)) %>% ungroup %>% group_by(depth)  %>% summarise(ubiomass = mean(ubiomass))
photicBiomass <- LubDf %>% filter(depth <= 165, depth >=155) %>% summarize(ubiomass = mean(ubiomass)) %>% pull(ubiomass)
LubDf <- LubDf %>% mutate(nbiomass = ubiomass/photicBiomass)
pWBL <- LubDf %>% ggplot(aes(x = nbiomass, y = depth)) + geom_path() + scale_y_reverse() + scale_x_continuous(limits = c(0,1)) + geom_hline(yintercept = 160, color = "darkgreen") + labs( x = "Large particle mass (norm.)") + geom_vline(xintercept = 1, color = "gray50") + geom_vline(xintercept = 0, color = "gray50") + geom_hline(yintercept = 850, color = "darkblue")
pWBL

For tom and danielle

WBColorMap

pWBPSD

pWBS

pWBL

WBFig5 <- plot_grid(pWBPSD, pWBS,pWBL, nrow = 1, labels = c("B", "C", "D"))
Removed 6 row(s) containing missing values (geom_path).Removed 7 row(s) containing missing values (geom_path).
WBFig5

WBcombined <- plot_grid(WBColorMap + theme(plot.margin = unit(c(0,3,0, 3), "cm")), WBFig5, ncol = 1, labels = c("A", ""))
WBcombined


ggsave("figures/WBModelValidation.png")
Saving 8 x 6 in image

P16 Flux

scientific_10 <- function(x) {parse(text=gsub("e\\+*", " %*% 10^", scales::scientific_format()(x))) }
#https://stackoverflow.com/questions/10762287/how-can-i-format-axis-labels-with-exponents-with-ggplot2-and-scales
#jacob_magnitude <- function(x){expression(10^round(log10(x)))}

cb10 <- c('#a6cee3','#1f78b4','#b2df8a','#33a02c','#fb9a99','#e31a1c','#fdbf6f','#ff7f00','#cab2d6','#6a3d9a')
pltFlxP16 <- bds %>% filter(project == "P16") %>% #filter(DFP > 1) %>% #filter(profile %in% c("stn_043", "p16n_100")) %>%
  ggplot(aes(y = depth, x = Flux_Smooth, group = factor(time)))  + geom_point(size = 3, stroke = 1)+
  geom_path() +
  scale_y_reverse(limits = c(1000, 0))+
  scale_x_log10(limits = c(35, 150),breaks = seq(from = 20, to = 150, by = 20)) +
   scale_color_gradient2(low = "darkgreen", mid = "gray80", high = "purple", midpoint = 10) + scale_shape_manual(name = "Day of Month", values = rep(21:25, 2)) + 
  scale_fill_gradientn(name = "Hour of Day", breaks = c(0, 6, 12, 18, 24), colors = c("black", "blue", "white", "orange", "black")) +
  
labs(x = bquote(Smoothed~Flux~(µmol~C/m^2/d)), y = "Depth (m)") +
  geom_hline(yintercept = 200, color = "darkgreen") +
  theme(axis.text.x = element_text(angle = 90, vjust = .3), legend.spacing = unit(.1, "cm"))
# 
# 
# 
# pltFlxNoLegend <- pltFlx + theme(legend.position = "none")
# pltFlxLegend <- get_legend(pltFlx)
# 
pltFlxP16

# #plotly::ggplotly(plt1)
cb10 <- c('#a6cee3','#1f78b4','#b2df8a','#33a02c','#fb9a99','#e31a1c','#fdbf6f','#ff7f00','#cab2d6','#6a3d9a')
pltDelta3P16 <- bds %>% filter(project == "P16") %>% #filter(DFP > 1) %>% #filter(profile %in% c("stn_043", "p16n_100")) %>%
  ggplot(aes(y = depth, x = pracma::nthroot(DF/DZ, 5), group = factor(time)))  + geom_point(size = 3, stroke = 1)+
  geom_path() +
  scale_y_reverse(limits = c(1000, 0))+
  scale_x_continuous(limits = c(-1, .1), breaks = seq(from = -2, to = .75, by = 0.5)) +
  #scale_x_log10() +
   scale_color_gradient2(low = "darkgreen", mid = "gray80", high = "purple", midpoint = 10) + scale_shape_manual(name = "Day of Month", values = rep(21:25, 2)) + 
  scale_fill_gradientn(name = "Hour", breaks = c(0, 6, 12, 18, 24), colors = c("black", "blue", "white", "orange", "black")) +
  geom_vline(xintercept = 0) +
  geom_hline(yintercept = 200, color = "darkgreen")+
  labs(x = bquote((DF/DZ)^{1/5}~(µmolC/m^3/d)^{1/5}), y = "Depth (m)") + theme(legend.pos = "none")
  #labs(x = "(DF/DZ) ^ 1/5 (µmol C/m^3/d) ^ 1/5")

pltDelta3P16

#plotly::ggplotly(plt1pos)
osms_p16 <- bds %>% filter(project == "P16") %>%
  ggplot(aes(y = depth, x = pracma::nthroot(ospsDZ, 3), group = factor(time))) + geom_point(size = 3) + geom_path() + scale_y_reverse(limits = c(1000, 0)) +
  scale_x_continuous(limits = c(-1, 1)) +
  geom_vline(xintercept = 0) +   scale_shape_manual(name = "Day of Month", values = rep(21:25, 2)) + labs(x = "Observed - Modeled Small Particle Flux \n µmol/m^3/day") +
  scale_fill_gradientn(name = "Hour of Day", breaks = c(0, 6, 12, 18, 24), colors = c("black", "blue", "white", "orange", "black")) + geom_hline(yintercept = 175, color = "darkgreen") 
plotly::ggplotly(osms_p16)

#ggsave("..figures/FluxSizeShift.svg"
plot_grid(
  pltFlxP16,
  pltDelta3P16,
  osms_p16
)
Removed 28 rows containing missing values (geom_point).Removed 28 row(s) containing missing values (geom_path).Removed 32 rows containing missing values (geom_point).Removed 32 row(s) containing missing values (geom_path).Removed 29 rows containing missing values (geom_point).Removed 29 row(s) containing missing values (geom_path).

ggsave("figures/P16FluxRelate.svg")
Saving 8 x 8 in image
ggsave("figures/P16FluxRelate.png")
Saving 8 x 8 in image

Flux attenuation example

source("ModelStuff.R")
scan_for_example <- bds %>% filter(project == "ETNP", depth < 500, depth > 200) %>% select(profile, depth, DFP, use_this_DFP, ospsDZ)

#loc_station = "stn_036"
loc_station = "stn_043"
loc_depth = 225
loc_prev_depth = 112.5

allDFPs <- bds %>% filter(profile == loc_station, depth >= loc_prev_depth, depth <= loc_depth) %>% summarize(DFP = prod(DFP), use_this_DFP = prod(use_this_DFP))

loc_DFP <-  allDFPs %>% pull(DFP)
loc_use_DFP <- allDFPs %>% pull(use_this_DFP)


for_single_disag <- bes %>% filter(profile == loc_station, depth %in% c(loc_prev_depth, loc_depth)) %>% select(depth, lb, nnp_smooth) %>%
  mutate(depth = recode(depth, `112.5` = "Shallow", `225` = "Deep")) %>% # I have no idea how to not hard code this bit
  pivot_wider(names_from = depth, values_from = nnp_smooth) 

with_disag <- for_single_disag %>%
  mutate(Predicted_Deep = remin_smooth_shuffle(Shallow, loc_use_DFP)) 
#remin_smooth_shuffle(for_single_disag$Shallow,loc_use_DFP)

for_plot_disag <- with_disag %>% pivot_longer(cols = -lb) %>% #filter(lb <= 5) %>%
  mutate(name = factor(name, levels = c("Shallow", "Deep", "Predicted_Deep"))) %>%
  mutate(name = recode_factor(name, Shallow = "Shallow (112.5m)", Deep = "Deep (225m)", Predicted_Deep = "Predicted Deep (225m)"))

for_plot_disag %>% ggplot(aes(x = lb, y = value, shape = name)) + geom_point() + scale_x_log10() + scale_y_log10() + scale_shape_manual(values = c(1, 6, 3)) + theme(legend.title = element_blank()) + labs(x = "Particle Size (mm)", y = "Normalized Particle Abundance (#/L/mm)")

ggsave("figures/DisagExample.png")
Saving 7.29 x 4.5 in image
ggsave("figures/DisagExample.svg")
Saving 7.29 x 4.5 in image

EK60

dataBinned <- read_csv("data/backscatter_table_go7.csv")
Parsed with column specification:
cols(
  frequency = col_double(),
  depth_bin = col_double(),
  time_bin = col_datetime(format = ""),
  value = col_double()
)
dataBinned_01 <- dataBinned %>%
  mutate(timeMex = with_tz(time_bin, tzone = "US/Central") )
startDay <- dataBinned_01$timeMex %>% na.omit %>% min %>% floor_date(unit = "days")
endDay <- dataBinned_01$timeMex %>% na.omit %>% max %>% ceiling_date(unit = "days")
timeBreaks <- seq(from = startDay, to = endDay, by = "12 hours")
timeLabels <- format(timeBreaks)
plotLetters <- tribble(
  ~letter, ~depth_bin, ~timeMex,
  "A", 350, as.POSIXct("2017-01-07 13:00:00"),
  "B", 200, as.POSIXct("2017-01-09 23:00:00"),
  "C", 150, as.POSIXct("2017-01-08 13:00:00"),
  "D", 625, as.POSIXct("2017-01-12 07:00:00"),
  "E", 750, as.POSIXct("2017-01-10 02:00:00")
  
)

library(shadowtext)
plot18k <- dataBinned_01 %>% filter(frequency == 18000) %>% ggplot(aes(x = timeMex, y = depth_bin, fill = value)) + geom_tile() + scale_y_reverse() + scale_fill_viridis_c(limits = c(-165, -75), oob = scales::squish) +
  scale_x_datetime(breaks = timeBreaks, date_labels = "%d::%H") + labs(x = "day::hour", y = "depth (m)", fill = "backscatter (dB)") + theme_bw() + theme(axis.text.x = element_text(angle = 90, vjust = 0.5)) + geom_hline(yintercept = 160, color = "darkgreen") +
  geom_hline(yintercept = 850, color = "darkblue") +
  geom_shadowtext(data = plotLetters, aes(x = timeMex - 12 * 60^2, y = depth_bin, label = letter),  inherit.aes = FALSE, size = 6, bg.color = "white", color = "black") +
  geom_segment(data = plotLetters, inherit.aes = FALSE, aes(x = timeMex - 9 * 60^2, xend = timeMex, y = depth_bin, yend = depth_bin), arrow = arrow(length = unit(0.03, "npc")), color = "white", size = 1.5) + 
  geom_segment(data = plotLetters, inherit.aes = FALSE, aes(x = timeMex - 9 * 60^2, xend = timeMex, y = depth_bin, yend = depth_bin), arrow = arrow(length = unit(0.03, "npc")))
plot18k


#ggsave("figures/stationP2_EK60_18kOnly.png")
plotLetters <- tribble(
  ~letter, ~depth_bin, ~timeMex,
  "A", 300, as.POSIXct("2017-01-07 13:00:00"),
  "B", 200, as.POSIXct("2017-01-09 23:00:00"),
  "C", 150, as.POSIXct("2017-01-08 13:00:00"),
  "D", 625, as.POSIXct("2017-01-12 07:00:00"),
  "E", 750, as.POSIXct("2017-01-10 02:00:00")
  
)

library(shadowtext)
plot38k <- dataBinned_01 %>% filter(frequency == 38000) %>% ggplot(aes(x = timeMex, y = depth_bin, fill = value)) + geom_tile() + scale_y_reverse() + scale_fill_viridis_c(limits = c(-165, -95), oob = scales::squish) +
  scale_x_datetime(breaks = timeBreaks, date_labels = "%d::%H") + labs(x = "Day::Hour", y = "Depth (m)", fill = "Backscatter (dB)") + theme_bw()  + geom_hline(yintercept = 160, color = "darkgreen") +
  geom_hline(yintercept = 850, color = "darkblue") +
  geom_shadowtext(data = plotLetters[1:2,], aes(x = timeMex - 12 * 60^2, y = depth_bin, label = letter),  inherit.aes = FALSE, size = 6, bg.color = "white", color = "black") +
  geom_segment(data = plotLetters[1:2,], inherit.aes = FALSE, aes(x = timeMex - 9 * 60^2, xend = timeMex, y = depth_bin, yend = depth_bin), arrow = arrow(length = unit(0.03, "npc")), color = "white", size = 1.5) + 
  geom_segment(data = plotLetters[1:2,], inherit.aes = FALSE, aes(x = timeMex - 9 * 60^2, xend = timeMex, y = depth_bin, yend = depth_bin), arrow = arrow(length = unit(0.03, "npc"))) +
  theme(axis.text.x = element_text(size = 12,angle = 90, vjust = 0.5),
        axis.text.y = element_text(size = 12),
        axis.title = element_text(size = 14),
        legend.title = element_text(size = 14)
        )
plot38k

ggsave("figures/stationP2_EK60_38kOnly.png")
Saving 7.29 x 4.5 in image

plot18k + scale_y_reverse(limits = c(500, 200))
Scale for 'y' is already present. Adding another scale for 'y', which will replace the existing scale.

plot200k <- dataBinned_01 %>% filter(frequency == 200000) %>% ggplot(aes(x = timeMex, y = depth_bin, fill = value)) + geom_tile() + scale_y_reverse() + scale_fill_viridis_c(limits = c(-165, -155), oob = scales::squish) +
  scale_x_datetime(breaks = timeBreaks, date_labels = "%d::%H") + labs(x = "day::hour", y = "depth (m)", fill = "backscatter (dB)") + theme_bw() + theme(axis.text.x = element_text(angle = 90, vjust = 0.5)) + geom_hline(yintercept = 160, color = "darkgreen") +
  geom_hline(yintercept = 850, color = "darkblue")
plot200k

dataBinned_01 %>% ggplot(aes(x = timeMex, y = depth_bin, fill = value)) + geom_tile() + scale_y_reverse() + scale_fill_viridis_c(limits = c(-165, -75), oob = scales::squish) +
  scale_x_datetime(breaks = timeBreaks, date_labels = "%d::%H") + labs(x = "day::hour", y = "Depth (m)", fill = "backscatter (dB)") + theme_bw() + theme(axis.text.x = element_text(angle = 90, vjust = 0.5)) +
  
  
  facet_wrap(~frequency, ncol = 1)


#ggsave("figures/stationP2_EK60_go7.svg", width = 4, height = 10)
ggsave("figures/stationP2_EK60_go7.png", width = 6, height = 10)
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkobHVicmlkYXRlKQpsaWJyYXJ5KG1nY3YpCnNvdXJjZSgiVVZQXzIwMTdfbGlicmFyeS5SIikKdGhlbWVfc2V0KHRoZW1lX2Nvd3Bsb3QoKSkKY2IxMCA8LSBjKCcjYTZjZWUzJywnIzFmNzhiNCcsJyNiMmRmOGEnLCcjMzNhMDJjJywnI2ZiOWE5OScsJyNlMzFhMWMnLCcjZmRiZjZmJywnI2ZmN2YwMCcsJyNjYWIyZDYnLCcjNmEzZDlhJykKYGBgCgoKIyBQYXJ0aWNsZXMgT25seQoKIyBSZWFkIEluIERhdGEKCmBgYHtyfQpiZXM8LSByZWFkX2NzdigiZGF0YU91dC9iaW5uZWRfRWFjaFNpemUuY3N2IikKYmRzIDwtIHJlYWRfY3N2KCJkYXRhT3V0L2Jpbm5lZF9EZXB0aFN1bW1hcnkuY3N2IikKdWVzIDwtIHJlYWRfY3N2KCJkYXRhT3V0L3VuYmlubmVkX0VhY2hTaXplLmNzdiIpCnVkcyA8LSByZWFkX2NzdigiZGF0YU91dC91bmJpbm5lZF9EZXB0aFN1bW1hcnkuY3N2IikKYGBgCgpgYGB7cn0KUGhvdGljQmFzZSA8LSAxNjAKT01aQmFzZSA8LSA4NTAKYGBgCgoKIyBTdW1tYXJ5IFN0YXRpc3RpY3MKYGBge3J9ClBsb3ROUGFydGljbGVzIDwtIHVkcyAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gdG90X25wYXJ0aWNsZXMsIHkgPSBkZXB0aCwgY29sID0gcHJvZmlsZSkpICsKIGZhY2V0X3dyYXAofnByb2plY3QpICsKIGdlb21fcG9pbnQoYWxwaGEgPSAwLjMsIHNoYXBlID0gMSkgKwpzY2FsZV95X3JldmVyc2UoKSArIHNjYWxlX3hfbG9nMTAoKQoKUGxvdE5QYXJ0aWNsZXMKYGBgCgpgYGB7cn0KYmRzQWRkVGltZSA8LSBiZHMgJT4lCiAgbXV0YXRlKEhvdXIgPSBob3VyKHRpbWUpLCBEYXkgPSBkYXkodGltZSkpCgpGU0cxIDwtIGdhbSh0b3RfbnBhcnRpY2xlc34gcyhkZXB0aCwgayA9IDMpICsgcyhEYXksIGsgPSAzKSArIHMoSG91ciwgayA9IDQsIGJzID0gImNjIiksIGtub3RzID0gbGlzdChIb3VyID0gYygwLCAyNCkpLCBkYXRhID0gYmRzQWRkVGltZSAlPiUgZmlsdGVyKGRlcHRoID49IDE3NSAmIGRlcHRoIDw9NTAwICYgcHJvamVjdCA9PSAiRVROUCIpKQoKRlNHMiA8LSBnYW0odG90X25wYXJ0aWNsZXMgfiBzKGRlcHRoLCBrID0gMykgKyBzKERheSwgayA9IDMpLCBkYXRhID0gYmRzQWRkVGltZSAlPiUgZmlsdGVyKGRlcHRoID49IDE3NSAmIGRlcHRoIDw9NTAwICYgcHJvamVjdCA9PSAiRVROUCIpKQoKRlNHMyA8LSBnYW0odG90X25wYXJ0aWNsZXMgfiBzKGRlcHRoLCBrID0gMyksIGRhdGEgPSBiZHNBZGRUaW1lICU+JSBmaWx0ZXIoZGVwdGggPj0gMTc1ICYgZGVwdGggPD01MDAgJiBwcm9qZWN0ID09ICJFVE5QIikpCgojRlNHNCA8LSBnYW0odG90X25wYXJ0aWNsZXN+IHMoZGVwdGgsIGsgPSAzKSAgKyBzKEhvdXIsIGsgPSA0LCBicyA9ICJjYyIpLCBrbm90cyA9IGxpc3QoSG91ciA9IGMoMCwgMjQpKSwgZGF0YSA9IGJkc0FkZFRpbWUgJT4lIGZpbHRlcihkZXB0aCA+PSAxNzUgJiBkZXB0aCA8PTUwMCAmIHByb2plY3QgPT0gIkVUTlAiKSkKCnN1bW1hcnkoRlNHMSkKI3N1bW1hcnkoRlNHMikKI3N1bW1hcnkoRlNHMykKI3N1bW1hcnkoRlNHNCkKCnN1bW1hcnkoRlNHMSkkci5zcSAtIHN1bW1hcnkoRlNHMikkci5zcQpzdW1tYXJ5KEZTRzIpJHIuc3EgLSBzdW1tYXJ5KEZTRzMpJHIuc3EKc3VtbWFyeShGU0czKSRyLnNxCmBgYAoKQnV0IHRoZXJlIGlzIGJldHdlZW4gcHJvamVjdHM6CmBgYHtyfQpQcm9qR2FtIDwtIGdhbSh0b3RfbnBhcnRpY2xlc34gcyhkZXB0aCwgayA9IDMpICsgZmFjdG9yKHByb2plY3QpLCBrbm90cyA9IGxpc3QoSG91ciA9IGMoMCwgMjQpKSwgZGF0YSA9IGJkc0FkZFRpbWUgJT4lIGZpbHRlcihkZXB0aCA+PSAxNzUgJiBkZXB0aCA8PTUwMCkpCgpzdW1tYXJ5KFByb2pHYW0pCmBgYAoKYGBge3IgZmlnLndpZHRoID0gMTJ9CmxpYnJhcnkoc2NhbGVzKQojaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMzAxNzk0NDIvcGxvdHRpbmctbWlub3ItYnJlYWtzLW9uLWEtbG9nLXNjYWxlLXdpdGgtZ2dwbG90CmxvZ19icmVha3MgPSBmdW5jdGlvbihtYWosIHJhZGl4PTEwKSB7CiAgZnVuY3Rpb24oeCkgewogICAgbWlueCAgICAgICAgID0gZmxvb3IobWluKGxvZ2IoeCxyYWRpeCksIG5hLnJtPVQpKSAtIDEKICAgIG1heHggICAgICAgICA9IGNlaWxpbmcobWF4KGxvZ2IoeCxyYWRpeCksIG5hLnJtPVQpKSArIDEKICAgIG5fbWFqb3IgICAgICA9IG1heHggLSBtaW54ICsgMQogICAgbWFqb3JfYnJlYWtzID0gc2VxKG1pbngsIG1heHgsIGJ5PTEpCiAgICBpZiAobWFqKSB7CiAgICAgIGJyZWFrcyA9IG1ham9yX2JyZWFrcwogICAgfSBlbHNlIHsKICAgICAgc3RlcHMgPSBsb2diKDE6KHJhZGl4LTEpLHJhZGl4KQogICAgICBicmVha3MgPSByZXAoc3RlcHMsIHRpbWVzPW5fbWFqb3IpICsKICAgICAgICAgICAgICAgcmVwKG1ham9yX2JyZWFrcywgZWFjaD1yYWRpeC0xKQogICAgfQogICAgcmFkaXheYnJlYWtzCiAgfQp9CnNjYWxlX3hfbG9nX2VuZyA9IGZ1bmN0aW9uKC4uLiwgcmFkaXg9MTApIHsKICBzY2FsZV94X2NvbnRpbnVvdXMoLi4uLAogICAgICAgICAgICAgICAgICAgICB0cmFucz1sb2dfdHJhbnMocmFkaXgpLAogICAgICAgICAgICAgICAgICAgICBicmVha3M9bG9nX2JyZWFrcyhUUlVFLCByYWRpeCksCiAgICAgICAgICAgICAgICAgICAgIG1pbm9yX2JyZWFrcz1sb2dfYnJlYWtzKEZBTFNFLCByYWRpeCkpCn0KCiN0aGVtZV9zZXQodGhlbWVfYncpClBsb3RQU0RtYW55IDwtIHVkcyAlPiUgCiAgZmlsdGVyKHByb2plY3QgPT0gIkVUTlAiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBwc2QsIHkgPSBkZXB0aCwgc2hhcGUgPSBmYWN0b3IoZGF5KHRpbWUpKSwgZmlsbCA9IGhvdXIodGltZSkpKSArCiAKICAjZ2VvbV9wYXRoKGFlcyh4ID0gcHNkX2dhbSkpICsgCiAgI2dlb21fcmliYm9uKGFlcyh4ID0gcHNkX2dhbSwgeG1pbiA9IHBzZF9nYW0gLSAyICogcHNkX3NlZywgeG1heCA9IHBzZF9nYW0gKyAyICogcHNkX3NlZyksIGFscGhhID0gMC4xLCBvdXRsaW5lX3R5cGUgPSAibG93ZXIiKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IC42LCBzaXplID0gMiwgc3Ryb2tlID0gMSkgKwogIHNjYWxlX3lfcmV2ZXJzZShsaW1pdHMgPSBjKDEyMDAsIDApKSArIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBjKDIxOjI1KSkgKwogIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKGJyZWFrcyA9IGMoMCwgNiwgMTIsIDE4LCAyNCksIGNvbG9ycyA9IGMoImJsYWNrIiwgImJsdWUiLCAid2hpdGUiLCAib3JhbmdlIiwgImJsYWNrIikpICsKICBsYWJzKHkgPSAiRGVwdGggKG0pIiwgeCA9ICJQYXJ0aWNsZSBTaXplIERpc3RyaWJ1dGlvbiBTbG9wZSIpICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMTc1LCBjb2xvciA9ICJkYXJrZ3JlZW4iKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gODUwLCBjb2xvciA9ICJkYXJrYmx1ZSIpIAoKI3RoZW1lX3NldCh0aGVtZV9jb3dwbG90KQoKUGxvdFBhcnRpY2xlc21hbnkgPC0gdWRzICU+JSAKICBmaWx0ZXIocHJvamVjdCA9PSAiRVROUCIpICU+JQogIGdncGxvdChhZXMoeCA9IHRvdF9ucGFydGljbGVzLCB5ID0gZGVwdGgsIHNoYXBlID0gZmFjdG9yKGRheSh0aW1lKSksIGZpbGwgPSBob3VyKHRpbWUpKSkgKwogCiAgI2dlb21fcGF0aChhZXMoeCA9IHBzZF9nYW0pKSArIAogICNnZW9tX3JpYmJvbihhZXMoeCA9IHBzZF9nYW0sIHhtaW4gPSBwc2RfZ2FtIC0gMiAqIHBzZF9zZWcsIHhtYXggPSBwc2RfZ2FtICsgMiAqIHBzZF9zZWcpLCBhbHBoYSA9IDAuMSwgb3V0bGluZV90eXBlID0gImxvd2VyIikgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAuNiwgc2l6ZSA9IDIsIHN0cm9rZSA9IDEpICsKICBzY2FsZV95X3JldmVyc2UobGltaXRzID0gYygxMjAwLCAwKSkgKyBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gYygyMToyNSkpICsKICBzY2FsZV9maWxsX2dyYWRpZW50bihicmVha3MgPSBjKDAsIDYsIDEyLCAxOCwgMjQpLCBjb2xvcnMgPSBjKCJibGFjayIsICJibHVlIiwgIndoaXRlIiwgIm9yYW5nZSIsICJibGFjayIpKSArCiAgc2NhbGVfeF9sb2cxMChicmVha3MgPSBjKDEwLCAxMDAsIDEwMDApLCBtaW5vciA9IGMoNSwgNTAsIDUwMCkpICsKICAjdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgI3NjYWxlX3hfbG9nX2VuZygpKwogIGxhYnMoeSA9ICJEZXB0aCAobSkiLCB4ID0gIlBhcnRpY2xlcyAvIEwiKSArIAogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDE3NSwgY29sb3IgPSAiZGFya2dyZWVuIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDg1MCwgY29sb3IgPSAiZGFya2JsdWUiKSAKCiMgUGxvdEZsdXhtYW55IDwtIHVkcyAlPiUgCiMgICBmaWx0ZXIocHJvamVjdCA9PSAiRVROUCIpICU+JQojICAgZ2dwbG90KGFlcyh4ID0gdG90X2ZsdXhfZml0LCB5ID0gZGVwdGgsIHNoYXBlID0gZmFjdG9yKGRheSh0aW1lKSksIGZpbGwgPSBob3VyKHRpbWUpKSkgKwojICAKIyAgICNnZW9tX3BhdGgoYWVzKHggPSBwc2RfZ2FtKSkgKyAKIyAgICNnZW9tX3JpYmJvbihhZXMoeCA9IHBzZF9nYW0sIHhtaW4gPSBwc2RfZ2FtIC0gMiAqIHBzZF9zZWcsIHhtYXggPSBwc2RfZ2FtICsgMiAqIHBzZF9zZWcpLCBhbHBoYSA9IDAuMSwgb3V0bGluZV90eXBlID0gImxvd2VyIikgKwojICAgZ2VvbV9wb2ludChhbHBoYSA9IC42LCBzaXplID0gMiwgc3Ryb2tlID0gMSkgKwojICAgc2NhbGVfeV9yZXZlcnNlKCkgKyBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gYygyMToyNSkpICsKIyAgIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKGJyZWFrcyA9IGMoMCwgNiwgMTIsIDE4LCAyNCksIGNvbG9ycyA9IGMoImJsYWNrIiwgImJsdWUiLCAid2hpdGUiLCAib3JhbmdlIiwgImJsYWNrIikpICsKIyAgIHNjYWxlX3hfbG9nMTAoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCgoKcGxvdF9ncmlkKAogIFBsb3RQYXJ0aWNsZXNtYW55LAogIFBsb3RQU0RtYW55LAogIHJlbF93aWR0aHMgPSBjKDIsIDMpCiAgKQoKZ2dzYXZlKCJmaWd1cmVzL1BhcnRpY2xlc1BTRE1hbnkucG5nIikKZ2dzYXZlKCJmaWd1cmVzL1BhcnRpY2xlc1BTRE1hbnkuc3ZnIikKCmBgYAoKYGBge3J9CmJkc0FkZFRpbWUgPC0gYmRzICU+JQogIG11dGF0ZShIb3VyID0gaG91cih0aW1lKSwgRGF5ID0gZGF5KHRpbWUpKQoKRlNHMSA8LSBnYW0ocHNkfiBzKGRlcHRoLCBrID0gMykgKyBzKERheSwgayA9IDMpICsgcyhIb3VyLCBrID0gNCwgYnMgPSAiY2MiKSwga25vdHMgPSBsaXN0KEhvdXIgPSBjKDAsIDI0KSksIGRhdGEgPSBiZHNBZGRUaW1lICU+JSBmaWx0ZXIoZGVwdGggPj0gMTc1ICYgZGVwdGggPD01MDAgJiBwcm9qZWN0ID09ICJFVE5QIikpCgpGU0cyIDwtIGdhbShwc2QgfiBzKGRlcHRoLCBrID0gMykgKyBzKERheSwgayA9IDMpLCBkYXRhID0gYmRzQWRkVGltZSAlPiUgZmlsdGVyKGRlcHRoID49IDE3NSAmIGRlcHRoIDw9NTAwICYgcHJvamVjdCA9PSAiRVROUCIpKQoKRlNHMyA8LSBnYW0ocHNkIH4gcyhkZXB0aCwgayA9IDMpLCBkYXRhID0gYmRzQWRkVGltZSAlPiUgZmlsdGVyKGRlcHRoID49IDE3NSAmIGRlcHRoIDw9NTAwICYgcHJvamVjdCA9PSAiRVROUCIpKQoKRlNHNCA8LSBnYW0ocHNkfiBzKGRlcHRoLCBrID0gMykgICsgcyhIb3VyLCBrID0gNCwgYnMgPSAiY2MiKSwga25vdHMgPSBsaXN0KEhvdXIgPSBjKDAsIDI0KSksIGRhdGEgPSBiZHNBZGRUaW1lICU+JSBmaWx0ZXIoZGVwdGggPj0gMTc1ICYgZGVwdGggPD01MDAgJiBwcm9qZWN0ID09ICJFVE5QIikpCgpzdW1tYXJ5KEZTRzEpCiNzdW1tYXJ5KEZTRzIpCiNzdW1tYXJ5KEZTRzMpCnN1bW1hcnkoRlNHNCkKCnN1bW1hcnkoRlNHMSkkci5zcSAtIHN1bW1hcnkoRlNHMikkci5zcQpzdW1tYXJ5KEZTRzIpJHIuc3EgLSBzdW1tYXJ5KEZTRzMpJHIuc3EKc3VtbWFyeShGU0czKSRyLnNxCmBgYApOb3QgYSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGluIFBTRCB3aXRoIHJlc3BlY3QgdG8gdGltZS4KCkJ1dCB0aGVyZSBpcyBiZXR3ZWVuIHByb2plY3RzOgpgYGB7cn0KUHJvakdhbSA8LSBnYW0ocHNkfiBzKGRlcHRoLCBrID0gMykgKyBmYWN0b3IocHJvamVjdCksIGtub3RzID0gbGlzdChIb3VyID0gYygwLCAyNCkpLCBkYXRhID0gYmRzQWRkVGltZSAlPiUgZmlsdGVyKGRlcHRoID49IDE3NSAmIGRlcHRoIDw9NTAwKSkKCnN1bW1hcnkoUHJvakdhbSkKYGBgCgoKCgpJIHdvbmRlciBpZiBJIGNhbiBzaG93IHRoYXQgdGhlIHByb2ZpbGVzIGFyZW4ndCBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW5sdHkgZGlmZmVyZW50LiBPciB0aGF0IHRoZXkgYXJlIGZvciB0aGF0IG1hdHRlci4uLgpJIHRoaW5rIGluIHRoYXQgY2FzZSwgSSBydW4gYSBnYW0gd2l0aCBhbmQgd2l0aG91dCBhIHBhcmFtZXRlciBmb3IgcHJvZmlsZS4uLgpBbmQgdGhlbiBxdWFudGlmeSB0aGUgZWZmZWN0IHNpemUgb2YgdGhhdCBwYXJhbWV0ZXIKCk9yIGZvbGxvdyB0aGlzIEdhdmluIFNpbXBzb24gUG9zdApodHRwczovL2Zyb210aGVib3R0b21vZnRoZWhlYXAubmV0LzIwMTcvMTAvMTAvZGlmZmVyZW5jZS1zcGxpbmVzLWkvCgpvciAKYW5vdmEuZ2FtIHttZ2N2fQoKQ2FsY3VsYXRlIGdhbXMgZm9yIGVhY2ggcHJvZmlsZSwgYW5kIHRoZW4gcnVuIGFub3ZhLmdhbSB0byBzZWUgaWYgdGhleSBhcmUgZGlmZmVyZW50Li4uCgpgYGB7cn0KUGxvdE5QYXJ0aWNsZXNFUCA8LSB1ZHMgJT4lIAogIGZpbHRlcihwcm9maWxlICVpbiUgYygic3RuXzA0MyIsICJwMTZuXzEwMCIpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSB0b3RfbnBhcnRpY2xlcywgeSA9IGRlcHRoLCBjb2wgPSBwcm9qZWN0LCBzaGFwZSA9IHByb2plY3QpKSArCiBnZW9tX3BvaW50KGFscGhhID0gMC43LCBzaXplID0gMiwgc3Ryb2tlID0gMSkgKwogICNnZW9tX3BhdGgoYWVzKHggPSB0b3RfbnBhcnRpY2xlcykpICsKICAjZ2VvbV9yaWJib24oYWVzKHggPSBwc2RfZ2FtLCB4bWluID0gcHNkX2dhbSAtIDIgKiBwc2Rfc2VnLCB4bWF4ID0gcHNkX2dhbSArIDIgKiBwc2Rfc2VnKSwgYWxwaGEgPSAwLjEpICsKc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTAwMCwgMCkpICsgc2NhbGVfeF9sb2cxMCgpICsgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoImdyYXkyMCIsICJicm93biIpKSArCiAgbGFicyh4ID0gIlBhcnRpY2xlcy9MIiwgeSA9ICJEZXB0aCAobSkiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IGMoMTo1KSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDE3NSwgY29sb3IgPSAiZGFya2dyZWVuIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDIwMCwgY29sb3IgPSAiZGFya2dyZWVuIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDg1MCwgY29sb3IgPSAiZGFya2JsdWUiKSAKClBsb3ROUGFydGljbGVzRVAKYGBgCgpJIHJlbW92ZWQgb25lIG91dGx5ZXIgZnJvbSBwMTYgZm9yIHZpc3VhbGl6YXRpb24gcHVycG9zZXMgKDMwMCBwYXJ0aWNsZXMvbCBhdCBzdXJmYWNlKQoKYGBge3J9ClBsb3RQU0RFUCA8LSB1ZHMgJT4lIAogIGZpbHRlcihwcm9maWxlICVpbiUgYygic3RuXzA0MyIsICJwMTZuXzEwMCIpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBwc2QsIHkgPSBkZXB0aCwgY29sID0gcHJvamVjdCwgc2hhcGUgPSBwcm9qZWN0KSkgKwogZ2VvbV9wb2ludChhbHBoYSA9IDAuNywgc2l6ZSA9IDIsIHN0cm9rZSA9IDEpICsKICBnZW9tX3BhdGgoYWVzKHggPSBwc2RfZ2FtKSkgKwogIGdlb21fcmliYm9uKGFlcyh4ID0gcHNkX2dhbSwgeG1pbiA9IHBzZF9nYW0gLSAyICogcHNkX3NlZywgeG1heCA9IHBzZF9nYW0gKyAyICogcHNkX3NlZyksIGFscGhhID0gMC4xKSArCnNjYWxlX3lfcmV2ZXJzZShsaW1pdHMgPSBjKDEwMDAsIDApKSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJncmF5MjAiLCAiYnJvd24iKSkgICsKICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gYygxOjUpKSArIGxhYnMoeSA9ICIiLCB4ID0gIlBhcnRpY2xlIFNpemUgRGlzdHJpYnV0aW9uIFNsb3BlIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDE3NSwgY29sb3IgPSAiZGFya2dyZWVuIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDIwMCwgY29sb3IgPSAiZGFya2dyZWVuIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDg1MCwgY29sb3IgPSAiZGFya2JsdWUiKSAKClBsb3RQU0RFUApgYGAKCkkgbWF5IGp1c3QgY293IHRoZXNlIHRvZ3RoZXIuCgpgYGB7ciBmaWcud2lkdGggPSAxMCwgZmlnLmhlaWdodCA9IDR9CnBsb3RfZ3JpZChQbG90TlBhcnRpY2xlc0VQLCBQbG90UFNERVAsIHJlbF93aWR0aHMgPSBjKDIsMyksIGxhYmVscyA9IGMoIkEiLCAiQiIpKQpnZ3NhdmUoImZpZ3VyZXMvUGFydGljbGVzQW5kUFNEX0VUTlBWc1AxNi5zdmciKQpnZ3NhdmUoImZpZ3VyZXMvUGFydGljbGVzQW5kUFNEX0VUTlBWc1AxNi5wbmciKQpgYGAKCmBgYHtyfQptYWluUGFydGljbGVDb21wb25lbnRzIDwtIGJkcyAlPiUKICBmaWx0ZXIocHJvZmlsZSAlaW4lIGMoInN0bl8wNDMiLCAicDE2bl8xMDAiKSkgJT4lCiAgc2VsZWN0KHByb2plY3QsIHByb2ZpbGUsIGRlcHRoLAogICAgICAgICB0b3RfbnBhcnRpY2xlcywgc21hbGxfbnBhcnRpY2xlcywgYmlnX25wYXJ0aWNsZXMsCiAgICAgICAgIHRvdF9wc2QgPSBwc2QsIHNtYWxsX3BzZCwgYmlnX3BzZCwKICAgICAgICAgdG90X2ZsdXhfZml0LCBzbWFsbF9mbHV4X2ZpdCwgYmlnX2ZsdXhfZml0KSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IC1jKCJwcm9qZWN0IiwgInByb2ZpbGUiLCAiZGVwdGgiKSkgJT4lCiAgc2VwYXJhdGUobmFtZSwgYygic2l6ZSIsICJtZWFzIikpICU+JQogIG11dGF0ZShtZWFzID0gcmVjb2RlKG1lYXMsIG5wYXJ0aWNsZXMgPSAicGFydGljbGVzL0wiKSkgJT4lCiAgbXV0YXRlKG1lYXMgPSBmYWN0b3IobWVhcywgbGV2ZWxzID0gYygicGFydGljbGVzL0wiLCAiZmx1eCIsICJwc2QiKSkpCgpQbG90Rmx4IDwtIG1haW5QYXJ0aWNsZUNvbXBvbmVudHMgJT4lIAogIGZpbHRlcihtZWFzICE9ICJwc2QiKSAlPiUKICBnZ3Bsb3QoYWVzKHkgPSBkZXB0aCwgeCA9IHZhbHVlLCBjb2wgPSBwcm9qZWN0LCBzaGFwZSA9IHByb2plY3QpKSArIGZhY2V0X2dyaWQoc2l6ZSB+IG1lYXMsIHNjYWxlcyA9ICJmcmVlX3giKSArIGdlb21fcG9pbnQoc2l6ZSA9IDIpICsgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTAwMCwgMCkpICsgc2NhbGVfeF9sb2cxMCgpICsgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLCBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIHN0cmlwLmJhY2tncm91bmQueSA9IGVsZW1lbnRfYmxhbmsoKSwgc3RyaXAudGV4dC55ID0gZWxlbWVudF9ibGFuaygpLCBwbG90Lm1hcmdpbiA9IHVuaXQoYyg3LDAsNyw3KSwgInB0IikpICsgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoImJyb3duIiwgImdyYXkyMCIpKSArIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBjKDE6NSkpICsgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMTc1LCBjb2xvciA9ICJkYXJrZ3JlZW4iKQoKUGxvdFBTRCA8LSBtYWluUGFydGljbGVDb21wb25lbnRzICU+JSAKICBmaWx0ZXIobWVhcyA9PSAicHNkIikgJT4lCiAgZ2dwbG90KGFlcyh5ID0gZGVwdGgsIHggPSB2YWx1ZSwgY29sID0gcHJvamVjdCwgc2hhcGUgPSBwcm9qZWN0KSkgKyBmYWNldF9ncmlkKHNpemV+bWVhcywgc2NhbGVzID0gImZyZWVfeCIpICsgZ2VvbV9wb2ludChzaXplID0gMikgKyBzY2FsZV95X3JldmVyc2UobGltaXRzID0gYygxMDAwLCAwKSkgKwogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLmxpbmUueSA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwgcGxvdC5tYXJnaW4gPSB1bml0KGMoNyw3LDI2LjUsMCksICJwdCIpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoImJyb3duIiwgImdyYXkyMCIpKSArICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gYygxOjUpKSArICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkgKyBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAxNzUsIGNvbG9yID0gImRhcmtncmVlbiIpCgpwbG90X2dyaWQoUGxvdEZseCwgUGxvdFBTRCwgcmVsX3dpZHRocyA9IGMoMywgMikpCgpnZ3NhdmUoImZpZ3VyZXMvQmlnVnNTbWFsbC5zdmciKQpnZ3NhdmUoImZpZ3VyZXMvQmlnVnNTbWFsbC5wbmciKQpgYGAKCkZsdXggc21hbGwgYW5kIGZsdXggdG90IHRyYWNrIHNvIGNsb3NlbHkgYmVjYXVzZSBhZyA+IHBzZC4gc2luY2UgdGhlIHNpemUgZGlzdHJpYnV0aW9uIG9mIHRoZSBmbHV4IHNvdWxkIGJlIFBTRCArIGFnIChwc2QgaXMgbmVnYXRpdmUgaW4gdGhpcyBjYXNlKS4gWW8gdWNhbiBzZWUgdGhlIHZhcmlhbmNlIGF0IHRoZSBvbmUgZGVwdGggd2hlcmUgcHNkIGlzIGZsYXRlc3QgYXQgdGhlIHZlcnkgdG9wLgp0aW1lIDIwMTctMDEtMTMgMTc6NTE6MzEKMjAyLjQgTApgYGB7cn0KZWdfZGF0YWxpbmUgPC0gYmRzICU+JSAKICBmaWx0ZXIocHJvZmlsZSA9PSAic3RuXzA0MyIsIGRlcHRoID09IDE2Mi41KQplZ19zbG9wZSA9ICBlZ19kYXRhbGluZSAlPiUgcHVsbChwc2QpCmVnX2ljcCA9IGVnX2RhdGFsaW5lICU+JSBwdWxsKGljcCkKZWdfdm9sID0gZWdfZGF0YWxpbmUgJT4lIHB1bGwodm9sKQoKZWdfZGF0YWJsb2NrIDwtIGJlcyAlPiUKICBmaWx0ZXIocHJvZmlsZSA9PSAic3RuXzA0MyIsIGRlcHRoID09IDE2Mi41KQoKCmVnX2xiID0gZWdfZGF0YWJsb2NrJGxiCmVnX2JpbnNpemUgPSBlZ19kYXRhYmxvY2skYmluc2l6ZQplZ19ubnAgPSBleHAoZWdfaWNwICsgbG9nKGVnX2xiKSAqIGVnX3Nsb3BlKQoKZWdfbnAgPSBlZ19ubnAgKiBlZ19iaW5zaXplCmVnX3RwID0gZWdfbnAgKiBlZ192b2wKZWdfZGYgPC0gdGliYmxlKGxiID0gZWdfbGIsIG5fbnBhcnRpY2xlcyA9IGVnX25ucCwgbnBhcnRpY2xlcyA9IGVnX25wLCBUb3RhbFBhcnRpY2xlcyA9IGVnX3RwKQoKCkVnTk5QIDwtIGVnX2RhdGFibG9jayAlPiUKICBnZ3Bsb3QoYWVzKHggPSBsYiwgeSA9IG5fbnBhcnRpY2xlcykpICsgZ2VvbV9wb2ludCgpICsgc2NhbGVfeF9sb2cxMCgpICsgc2NhbGVfeV9sb2cxMCgpICsgCiAgZ2VvbV9wYXRoKGRhdGEgPSBlZ19kZikgKyBsYWJzKHkgPSAiQmluc2l6ZSAmIFZvbHVtZSBOb3JtYWxpemVkIFxuIFBhcnRpY2xlcyAoIy9ML21tKSIsIHggPSAiU2l6ZSAobW0pIikKCkVnTlAgPC0gZWdfZGF0YWJsb2NrICU+JQogIGdncGxvdChhZXMoeCA9IGxiLCB5ID0gbnBhcnRpY2xlcykpICsgZ2VvbV9wb2ludCgpICsgc2NhbGVfeF9sb2cxMCgpICsgc2NhbGVfeV9sb2cxMCgpICsgCiAgZ2VvbV9wYXRoKGRhdGEgPSBlZ19kZikgKyBsYWJzKHkgPSAiTm9ybWFsaXplZCBQYXJ0aWNsZXMiICwgeCA9ICJTaXplIChtbSkiKQoKRWdUUCA8LSBlZ19kYXRhYmxvY2sgJT4lCiAgZ2dwbG90KGFlcyh4ID0gbGIsIHkgPSBUb3RhbFBhcnRpY2xlcykpICsgZ2VvbV9wb2ludCgpICsgc2NhbGVfeF9sb2cxMCgpICsgc2NhbGVfeV9sb2cxMCgpICsgCiAgZ2VvbV9wYXRoKGRhdGEgPSBlZ19kZikgKyBsYWJzKCB5ID0gIlRvdGFsIFBhcnRpY2xlcyBPYnNlcnZlZCAoIykiLCB4ID0gIlNpemUgKG1tKSIpCgpwbG90X2dyaWQoRWdOTlAsIEVnVFAsIGxhYmVscyA9IGMoIkEiLCAiQiIpKQpnZ3NhdmUoImZpZ3VyZXMvRXhhbXBsZVBTRDE2M20ucG5nIikKZ2dzYXZlKCJmaWd1cmVzL0V4YW1wbGVQU0QxNjNtLnN2ZyIpCgpgYGAKCiMgU21vb3RoIGZsdXggYW5kIHVtIGRpc2FnZ3JlZ2F0aW9uLgoKYGBge3J9CmJkcyAlPiUgCiAgZ2dwbG90KGFlcyh5ID0gZGVwdGgsIHggPSBGbHV4X1Ntb290aCwgY29sID0gZmFjdG9yKHRpbWUpKSkgKyBmYWNldF93cmFwKH5wcm9qZWN0KSArIGdlb21fcG9pbnQoKSArIHNjYWxlX3lfcmV2ZXJzZShsaW1pdHMgPSBjKDEwMDAsIDApKSArIHNjYWxlX3hfbG9nMTAoKQpgYGAKCgoKCmBgYHtyfQpiZHNBZGRUaW1lIDwtIGJkcyAlPiUKICBtdXRhdGUoSG91ciA9IGhvdXIodGltZSksIERheSA9IGRheSh0aW1lKSkKCkZTRzEgPC0gZ2FtKEZsdXhfU21vb3RofiBzKGRlcHRoLCBrID0gMykgKyBzKERheSwgayA9IDMpICsgcyhIb3VyLCBrID0gNCwgYnMgPSAiY2MiKSwga25vdHMgPSBsaXN0KEhvdXIgPSBjKDAsIDI0KSksIGRhdGEgPSBiZHNBZGRUaW1lICU+JSBmaWx0ZXIoZGVwdGggPj0gMTc1ICYgZGVwdGggPD01MDAgJiBwcm9qZWN0ID09ICJFVE5QIikpCgpGU0cyIDwtIGdhbShGbHV4X1Ntb290aCB+IHMoZGVwdGgsIGsgPSAzKSArIHMoRGF5LCBrID0gMyksIGRhdGEgPSBiZHNBZGRUaW1lICU+JSBmaWx0ZXIoZGVwdGggPj0gMTc1ICYgZGVwdGggPD01MDAgJiBwcm9qZWN0ID09ICJFVE5QIikpCgpGU0czIDwtIGdhbShGbHV4X1Ntb290aCB+IHMoZGVwdGgsIGsgPSAzKSwgZGF0YSA9IGJkc0FkZFRpbWUgJT4lIGZpbHRlcihkZXB0aCA+PSAxNzUgJiBkZXB0aCA8PTUwMCAmIHByb2plY3QgPT0gIkVUTlAiKSkKCnN1bW1hcnkoRlNHMSkKc3VtbWFyeShGU0cyKQpzdW1tYXJ5KEZTRzMpCgpzdW1tYXJ5KEZTRzEpJHIuc3EgLSBzdW1tYXJ5KEZTRzIpJHIuc3EKc3VtbWFyeShGU0cyKSRyLnNxIC0gc3VtbWFyeShGU0czKSRyLnNxCnN1bW1hcnkoRlNHMykkci5zcQpgYGAKCmBgYHtyfQpiZHMgJT4lIGZpbHRlcihwcm9qZWN0ID09ICJFVE5QIikgJT4lIHNlbGVjdChwcm9maWxlLCBkZXB0aCwgRmx1eF9TbW9vdGgpICU+JSBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gcHJvZmlsZSwgdmFsdWVzX2Zyb20gPSBGbHV4X1Ntb290aCkKYGBgCgpTb21ldGhpbmcgaXMgb2ZmLiBBbGwgb2YgdGhlIGZsdXggcHJvZmlsZXMgYXJlIGlkZW50aWNhbC4KU2tpcCB0aGlzCmBgYHtyfQpjYjEwIDwtIGMoJyNhNmNlZTMnLCcjMWY3OGI0JywnI2IyZGY4YScsJyMzM2EwMmMnLCcjZmI5YTk5JywnI2UzMWExYycsJyNmZGJmNmYnLCcjZmY3ZjAwJywnI2NhYjJkNicsJyM2YTNkOWEnKQpwbHQxIDwtIGJkcyAlPiUgI2ZpbHRlcihERlAgPiAxKSAlPiUgI2ZpbHRlcihwcm9maWxlICVpbiUgYygic3RuXzA0MyIsICJwMTZuXzEwMCIpKSAlPiUKICBnZ3Bsb3QoYWVzKHkgPSBkZXB0aCwgeCA9IERGUCwgY29sID0gZmFjdG9yKHRpbWUpLCBzaGFwZSA9IGZhY3Rvcih0aW1lKSkpICsgZmFjZXRfd3JhcCh+cHJvamVjdCkgKyBnZW9tX3BvaW50KCkgKyBzY2FsZV95X3JldmVyc2UobGltaXRzID0gYygxMDAwLCAwKSkgKyB4bGltKGMoMC41LCAxLjUpKSsgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMSkgKwogICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYyhyZXAoImJsYWNrIiwgNSksIHJlcCgiYmx1ZSIsIDUpKSkgKyBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gcmVwKDE6NSwgMikpCgpwbG90bHk6OmdncGxvdGx5KHBsdDEpCmBgYAoKV2hhdCB0aGUgaGVjayBpcyBnb2luZyBvbiB3aXRoIERGUCBoZXJlLiBXaHkgaXMgaXQgdXN1YWxseSA+IDEgc2hvdWxkbid0IGl0IGJlIGxlc3MgdGhhbiAxIHdoZW4gZmx1eCBpcyBkZWNyZWFzaW5nPwpUaGlzIHZlcnkgZGVlcCBpbmNyZWFzaW5nIGZsdXggc2VlbXMgaW1wcm9iYWJsZSB0byBtZS4KTGV0cyBjaGVjayB0aGUgc21vb3Rocy4gT3Igb25seSBnbyB0byAxMDAwbS4KCiwgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5ib3guYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdCgpCmBgYHtyIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTR9CnNjaWVudGlmaWNfMTAgPC0gZnVuY3Rpb24oeCkge3BhcnNlKHRleHQ9Z3N1YigiZVxcKyoiLCAiICUqJSAxMF4iLCBzY2FsZXM6OnNjaWVudGlmaWNfZm9ybWF0KCkoeCkpKSB9CnNjaWVudGlmaWNfMTBfYiA8LSBmdW5jdGlvbih4KSB7cGFyc2UodGV4dD1nc3ViKCJlXFwrKiIsICIgJSolIDEwXiIsIHNjYWxlczo6c2NpZW50aWZpY19mb3JtYXQoKSh4KSkpIH0KCnNjaWVudGlmaWNfMTBfYyA8LSBmdW5jdGlvbih4KSB7CiAgICB4b3V0IDwtIGdzdWIoIjFlIiwgIjEwXnsiLCBmb3JtYXQoeCksZml4ZWQ9VFJVRSkKICAgIHhvdXQgPC0gZ3N1Yigiey0wIiwgInstIiwgeG91dCxmaXhlZD1UUlVFKQogICAgeG91dCA8LSBnc3ViKCJ7KyIsICJ7IiwgeG91dCxmaXhlZD1UUlVFKQogICAgeG91dCA8LSBnc3ViKCJ7MCIsICJ7IiwgeG91dCxmaXhlZD1UUlVFKQogICAgeG91dCA8LSBwYXN0ZSh4b3V0LCJ9IixzZXA9IiIpCiAgICByZXR1cm4ocGFyc2UodGV4dD14b3V0KSkKICAgIAp9CgpzY2FsZV94X2xvZzEwbmljZSA8LSBmdW5jdGlvbihuYW1lPU5VTEwsb21hZz1zZXEoLTEwLDIwKSwuLi4pIHsKICAgIGJyZWFrczEwIDwtIDEwXm9tYWcKICAgIHNjYWxlX3hfbG9nMTAoYnJlYWtzPWJyZWFrczEwLGxhYmVscz1zY2llbnRpZmljXzEwX2MoYnJlYWtzMTApLC4uLikKfQoKCiNodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8xMDc2MjI4Ny9ob3ctY2FuLWktZm9ybWF0LWF4aXMtbGFiZWxzLXdpdGgtZXhwb25lbnRzLXdpdGgtZ2dwbG90Mi1hbmQtc2NhbGVzCiNqYWNvYl9tYWduaXR1ZGUgPC0gZnVuY3Rpb24oeCl7ZXhwcmVzc2lvbigxMF5yb3VuZChsb2cxMCh4KSkpfQoKY2IxMCA8LSBjKCcjYTZjZWUzJywnIzFmNzhiNCcsJyNiMmRmOGEnLCcjMzNhMDJjJywnI2ZiOWE5OScsJyNlMzFhMWMnLCcjZmRiZjZmJywnI2ZmN2YwMCcsJyNjYWIyZDYnLCcjNmEzZDlhJykKcGx0Rmx4IDwtIGJkcyAlPiUgZmlsdGVyKHByb2plY3QgPT0gIkVUTlAiKSAlPiUgI2ZpbHRlcihERlAgPiAxKSAlPiUgI2ZpbHRlcihwcm9maWxlICVpbiUgYygic3RuXzA0MyIsICJwMTZuXzEwMCIpKSAlPiUKICBnZ3Bsb3QoYWVzKHkgPSBkZXB0aCwgeCA9IEZsdXhfU21vb3RoLCBzaGFwZSA9IGZhY3RvcihkYXkodGltZSkpLCBmaWxsID0gaG91cih0aW1lKSwgZ3JvdXAgPSBmYWN0b3IodGltZSkpKSAgKyBnZW9tX3BvaW50KHNpemUgPSAyLCBzdHJva2UgPSAxKSsKICAjZ2VvbV9wYXRoKCkgKwogIHNjYWxlX3lfcmV2ZXJzZShsaW1pdHMgPSBjKDEwMDAsIDApKSsKICBzY2FsZV94X2xvZzEwbmljZSgpKwogICNzY2FsZV94X2xvZzEwKCkgKyAKICAgc2NhbGVfY29sb3JfZ3JhZGllbnQyKGxvdyA9ICJkYXJrZ3JlZW4iLCBtaWQgPSAiZ3JheTgwIiwgaGlnaCA9ICJwdXJwbGUiLCBtaWRwb2ludCA9IDEwKSArIHNjYWxlX3NoYXBlX21hbnVhbChuYW1lID0gIkRheSBvZiBNb250aCIsIHZhbHVlcyA9IHJlcCgyMToyNSwgMikpICsgCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4obmFtZSA9ICJIb3VyIG9mIERheSIsIGJyZWFrcyA9IGMoMCwgNiwgMTIsIDE4LCAyNCksIGNvbG9ycyA9IGMoImJsYWNrIiwgImJsdWUiLCAid2hpdGUiLCAib3JhbmdlIiwgImJsYWNrIikpICsKICAKICBsYWJzKHggPSBicXVvdGUoU21vb3RoZWR+Rmx1eH4owrVtb2x+Qy9tXjIvZCkpLCB5ID0gIkRlcHRoIChtKSIpICsKICAjbGFicyh4ID0gIm1vbyIsIHkgPSAiRGVwdGggKG0pIikgKwogIGdlb21fcmVjdChkYXRhID0gZGF0YS5mcmFtZShwcm9qZWN0ID0gIkVUTlAiKSwgYWVzKHhtaW4gPSAyMCwgeG1heCA9IDE4MCwgeW1pbiA9IDc1LCB5bWF4ID0gNTAwKSwgY29sb3VyID0gInJlZCIsIGZpbGwgPSBOQSwgaW5oZXJpdC5hZXMgPSBGQUxTRSkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHZqdXN0ID0gLjMpLCBsZWdlbmQuc3BhY2luZyA9IHVuaXQoLjEsICJjbSIpKSArCiAgIGdlb21fc2VnbWVudChhZXMoeSA9IDE2MCwgeWVuZCA9IDE2MCwgeCA9IDIwLCB4ZW5kID0gNTAwKSwgY29sb3IgPSAiZGFya2dyZWVuIiwgc3Ryb2tlID0gMC41KSsKICAgZ2VvbV9zZWdtZW50KGFlcyh5ID0gODUwLCB5ZW5kID0gODUwLCB4ID0gMjAsIHhlbmQgPSA1MDApLCBjb2xvciA9ICJkYXJrYmx1ZSIsIHN0cm9rZSA9IDAuNSkjKyBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSA4NTAsIGNvbG9yID0gImRhcmtibHVlIikKCgoKcGx0Rmx4Tm9MZWdlbmQgPC0gcGx0Rmx4ICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQpwbHRGbHhMZWdlbmQgPC0gZ2V0X2xlZ2VuZChwbHRGbHgpCgpwbHRGbHgKI3Bsb3RseTo6Z2dwbG90bHkocGx0MSkKYGBgCgpgYGB7ciBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD00fQpjYjEwIDwtIGMoJyNhNmNlZTMnLCcjMWY3OGI0JywnI2IyZGY4YScsJyMzM2EwMmMnLCcjZmI5YTk5JywnI2UzMWExYycsJyNmZGJmNmYnLCcjZmY3ZjAwJywnI2NhYjJkNicsJyM2YTNkOWEnKQpwbHRGbHhab29tIDwtIGJkcyAlPiUgZmlsdGVyKHByb2plY3QgPT0gIkVUTlAiICYgZGVwdGggPD0gNTAwICYgZGVwdGggPj0gNzUpICU+JSAjZmlsdGVyKHByb2ZpbGUgJWluJSBjKCJzdG5fMDQzIiwgInAxNm5fMTAwIikpICU+JQogIGdncGxvdChhZXMoeSA9IGRlcHRoLCB4ID0gRmx1eF9TbW9vdGgsIHNoYXBlID0gZmFjdG9yKGRheSh0aW1lKSksIGZpbGwgPSBob3VyKHRpbWUpLCBncm91cCA9IGZhY3Rvcih0aW1lKSkpICsgZ2VvbV9wb2ludChzaXplID0gMiwgc3Ryb2tlID0gMSkrCiAgI2dlb21fcGF0aCgpICsKICBzY2FsZV95X3JldmVyc2UoKSsKICAjc2NhbGVfeF9sb2cxMCgpICsKICBzY2FsZV94X2xvZzEwKGJyZWFrcyA9IGMoc2VxKGZyb20gPSAyMCwgdG8gPSA1MCwgYnkgPSAxMCksIHNlcShmcm9tID0gNjAsIHRvID0gMTgwLCBieSA9IDIwKSksIGxpbWl0cyA9IGMoMjAsIDE4MCkpICsKICAgc2NhbGVfY29sb3JfZ3JhZGllbnQyKGxvdyA9ICJkYXJrZ3JlZW4iLCBtaWQgPSAiZ3JheTgwIiwgaGlnaCA9ICJwdXJwbGUiLCBtaWRwb2ludCA9IDEwKSArIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSByZXAoMjE6MjUsIDIpKSArIAogIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKGJyZWFrcyA9IGMoMCwgNiwgMTIsIDE4LCAyNCksIGNvbG9ycyA9IGMoImJsYWNrIiwgImJsdWUiLCAid2hpdGUiLCAib3JhbmdlIiwgImJsYWNrIikpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkgKwpsYWJzKHggPSAiU21vb3RoZWQgRmx1eCIsIHkgPSAiRGVwdGgiKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikrCmdlb21faGxpbmUoeWludGVyY2VwdCA9IDE2MCwgY29sb3IgPSAiZGFya2dyZWVuIikKCnBsdEZseFpvb20KI3Bsb3RseTo6Z2dwbG90bHkocGx0MSkKYGBgCgoKCmBgYHtyIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTR9CmNiMTAgPC0gYygnI2E2Y2VlMycsJyMxZjc4YjQnLCcjYjJkZjhhJywnIzMzYTAyYycsJyNmYjlhOTknLCcjZTMxYTFjJywnI2ZkYmY2ZicsJyNmZjdmMDAnLCcjY2FiMmQ2JywnIzZhM2Q5YScpCnBsdERlbHRhMyA8LSBiZHMgJT4lIGZpbHRlcihwcm9qZWN0ID09ICJFVE5QIikgJT4lICNmaWx0ZXIoREZQID4gMSkgJT4lICNmaWx0ZXIocHJvZmlsZSAlaW4lIGMoInN0bl8wNDMiLCAicDE2bl8xMDAiKSkgJT4lCiAgZ2dwbG90KGFlcyh5ID0gZGVwdGgsIHggPSBwcmFjbWE6Om50aHJvb3QoREYvRFosIDUpLCBzaGFwZSA9IGZhY3RvcihkYXkodGltZSkpLCBmaWxsID0gaG91cih0aW1lKSwgZ3JvdXAgPSBmYWN0b3IodGltZSkpKSAgKyBnZW9tX3BvaW50KHNpemUgPSAyLCBzdHJva2UgPSAxKSsKICAjZ2VvbV9wYXRoKCkgKwogIHNjYWxlX3lfcmV2ZXJzZShsaW1pdHMgPSBjKDEwMDAsIDApKSsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtMi4xLCAuNiksIGJyZWFrcyA9IHNlcShmcm9tID0gLTIsIHRvID0gLjc1LCBieSA9IDAuNSkpICsKICAjc2NhbGVfeF9sb2cxMCgpICsKICAgc2NhbGVfY29sb3JfZ3JhZGllbnQyKGxvdyA9ICJkYXJrZ3JlZW4iLCBtaWQgPSAiZ3JheTgwIiwgaGlnaCA9ICJwdXJwbGUiLCBtaWRwb2ludCA9IDEwKSArIHNjYWxlX3NoYXBlX21hbnVhbChuYW1lID0gIkRheSBvZiBNb250aCIsIHZhbHVlcyA9IHJlcCgyMToyNSwgMikpICsgCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4obmFtZSA9ICJIb3VyIiwgYnJlYWtzID0gYygwLCA2LCAxMiwgMTgsIDI0KSwgY29sb3JzID0gYygiYmxhY2siLCAiYmx1ZSIsICJ3aGl0ZSIsICJvcmFuZ2UiLCAiYmxhY2siKSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDApICsKICBsYWJzKHggPSBicXVvdGUoKERGL0RaKV57MS81fX4owrVtb2xDL21eMy9kKV57MS81fSksIHkgPSAiRGVwdGggKG0pIikgKyB0aGVtZShsZWdlbmQucG9zID0gIm5vbmUiKSsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAxNjAsIGNvbG9yID0gImRhcmtncmVlbiIpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gODUwLCBjb2xvciA9ICJkYXJrYmx1ZSIpCiAgI2xhYnMoeCA9ICIoREYvRFopIF4gMS81ICjCtW1vbCBDL21eMy9kKSBeIDEvNSIpCgpwbHREZWx0YTMKI3Bsb3RseTo6Z2dwbG90bHkocGx0MXBvcykKYGBgCgoKYGBge3IgZmlnLmhlaWdodD04LCBmaWcud2lkdGggPSA4fQojICNwbG90X2dyaWQocGx0Rmx4Tm9MZWdlbmQsIHBsdEZseFpvb20sIHBsdERlbHRhMywgcGx0Rmx4TGVnZW5kKQojIAojIHBsdEZseExlZ2VuZCA8LSBnZXRfbGVnZW5kKHBsdEZseCArIHRoZW1lKGxlZ2VuZC5ib3gubWFyZ2luID0gbWFyZ2luKDAsIDAsIDQwLCAxMCkpKQojIAojIHBnVG9wIDwtIHBsb3RfZ3JpZChwbHRGbHhOb0xlZ2VuZCwgcGx0Rmx4Wm9vbSArIHRoZW1lKHBsb3QubWFyZ2luID0gdW5pdChjKDEsIDAsIDMsIDApLCB1bml0cyA9ICJjbSIpKSwgcmVsX3dpZHRocyA9IGMoMiwgMSksIGxhYmVscyA9IGMoIkEiLCAiQiIpKQojIHBnQm90dG9tIDwtIHBsb3RfZ3JpZChwbHREZWx0YTMsIHBsdEZseExlZ2VuZCAsIHJlbF93aWR0aHMgPSBjKDMsIDEpLCBsYWJlbHMgPSBjKCJDIiwgIiIpLCBsYWJlbF9zaXplID0gMTQpCiMgcGdCb3RoIDwtIHBsb3RfZ3JpZChwZ1RvcCwgcGdCb3R0b20sIG5jb2wgPSAxKQojIAojIHBnQm90aAojIAojIGdnc2F2ZSgiZmlndXJlcy9GbHV4RGVlcERpdmUucG5nIikKIyBnZ3NhdmUoImZpZ3VyZXMvRmx1eERlZXBEaXZlLnN2ZyIpCgpgYGAKCgpXaXRoaW4gcGFuZWwgZHJhd2luZwoKCmBgYHtyIGZpZy5oZWlnaHQgPSA1LCBmaWcud2lkdGggPSA1fQpwZ1RvcCA8LSBnZ2RyYXcocGx0Rmx4Tm9MZWdlbmQgCiAgICAgICApICsKICBkcmF3X3Bsb3QocGx0Rmx4Wm9vbSwgLjQsIC4yNSwgLjU1LCAuNjApICsKICBkcmF3X3Bsb3RfbGFiZWwoCiAgICBjKCIiLCJCIiksCiAgICBjKC4wNSwgMC41NSksCiAgICBjKDEsIDAuODUpLAogICAgc2l6ZSA9IDE2CiAgKQpwZ1RvcApgYGAKcGdCb3R0b20gPC0gcGxvdF9ncmlkKHBsdERlbHRhMywgcGx0Rmx4TGVnZW5kICwgcmVsX3dpZHRocyA9IGMoMywgMSksIGxhYmVscyA9IGMoIkMiLCAiIiksIGxhYmVsX3NpemUgPSAxNCkKCgoKCkkgZG9uJ3Qga25vdyB3aGF0cyBnb2luZyBvbiBiZWxvdyBoZXJlCgpgYGB7ciBmaWcuaGVpZ2h0ID0gOSwgZmlnLndpZHRoID0gNX0KcGdCb3R0b20gPC0gcGx0RGVsdGEzICArIGdlb21fcmVjdChhZXMoeG1pbiA9IC0yLCB4bWF4ID0gLTEuMTUsIHltaW4gPSAxNzAsIHltYXggPSAxMDAwKSwgY29sb3VyID0gImdyYXk1MCIsIGZpbGwgPSBOQSwgaW5oZXJpdC5hZXMgPSBGQUxTRSkgKyBkcmF3X3Bsb3QocGx0Rmx4TGVnZW5kICwgLTEuOSwgLTU3NSwgLjcpCnBnQm90aCA8LSBwbG90X2dyaWQocGdUb3AgKyB0aGVtZShwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgdW5pdHMgPSAiY20iKSksCiAgICAgICAgICAgICAgICAgICAgcGdCb3R0b20gKyB0aGVtZShwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgdW5pdHMgPSAiY20iKSksCiAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDEsIHJlbF9oZWlnaHRzID0gYyg0LCA0KSwgbGFiZWxzID0gYygiQSIsICJDIiksIGxhYmVsX3NpemUgPSAxNikKcGdCb3RoCgpnZ3NhdmUoImZpZ3VyZXMvRmx1eERlZXBEaXZlLnBuZyIpCmdnc2F2ZSgiZmlndXJlcy9GbHV4RGVlcERpdmUuc3ZnIikKYGBgCgoKCmBgYHtyIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoID0gOH0KIyAjcGxvdF9ncmlkKHBsdEZseE5vTGVnZW5kLCBwbHRGbHhab29tLCBwbHREZWx0YTMsIHBsdEZseExlZ2VuZCkKIyAKIyBwbHRGbHhMZWdlbmQgPC0gZ2V0X2xlZ2VuZChwbHRGbHggKyB0aGVtZShsZWdlbmQuYm94Lm1hcmdpbiA9IG1hcmdpbigwLCAwLCA0MCwgMTApKSkKIyAKIyBwZ1RvcCA8LSBwbG90X2dyaWQocGx0Rmx4Tm9MZWdlbmQgKyB5bGltKGMoMTAwMCwgMCkpLCBwbHRGbHhab29tICsgdGhlbWUocGxvdC5tYXJnaW4gPSB1bml0KGMoMSwgMCwgMywgMCksIHVuaXRzID0gImNtIikpLCByZWxfd2lkdGhzID0gYygyLCAxKSwgbGFiZWxzID0gYygiQSIsICJCIikpCiMgcGdCb3R0b20gPC0gcGxvdF9ncmlkKHBsdERlbHRhMyArIHlsaW0oYygxMDAwLCAwKSksIHBsdEZseExlZ2VuZCAsIHJlbF93aWR0aHMgPSBjKDMsIDEpLCBsYWJlbHMgPSBjKCJDIiwgIiIpKQojIHBnQm90aCA8LSBwbG90X2dyaWQocGdUb3AsIHBnQm90dG9tLCBuY29sID0gMSkKIyAKIyBwZ0JvdGgKIyAKIyAjZ2dzYXZlKCJmaWd1cmVzL0ZsdXhTaGFsbG93RGl2ZS5wbmciKQojICNnZ3NhdmUoImZpZ3VyZXMvRmx1eFNoYWxsb3dEaXZlLnN2ZyIpCgpgYGAKClRlc3QgZm9yIGRheSB0byBkYXkgYW5kIGhvdXJseSB2YXJpYWJpbGl0eSBpbiBkZWx0YSBmbHV4CmBgYHtyfQpiZHNBZGRUaW1lIDwtIGJkcyAlPiUgCiAgbXV0YXRlKEhvdXIgPSBob3VyKHRpbWUpLCBEYXkgPSBkYXkodGltZSkpCgpERkcxIDwtIGdhbShwcmFjbWE6Om50aHJvb3QoREYvRFosIDUpfiBzKGRlcHRoLCBrID0gMykgKyBzKERheSwgayA9IDMpICsgcyhIb3VyLCBrID0gNCwgYnMgPSAiY2MiKSwga25vdHMgPSBsaXN0KEhvdXIgPSBjKDAsIDI0KSksIGRhdGEgPSBiZHNBZGRUaW1lICU+JSBmaWx0ZXIoZGVwdGggPj0gMjUwICYgZGVwdGggPD01MDAgJiBwcm9qZWN0ID09ICJFVE5QIikpCgpERkcyIDwtIGdhbShwcmFjbWE6Om50aHJvb3QoREYvRFosIDUpIH4gcyhkZXB0aCwgayA9IDMpICsgcyhEYXksIGsgPSAzKSwgZGF0YSA9IGJkc0FkZFRpbWUgJT4lIGZpbHRlcihkZXB0aCA+PSAyNTAgJiBkZXB0aCA8PTUwMCAmIHByb2plY3QgPT0gIkVUTlAiKSkKCkRGRzMgPC0gZ2FtKHByYWNtYTo6bnRocm9vdChERi9EWiwgNSkgfiBzKGRlcHRoLCBrID0gMyksIGRhdGEgPSBiZHNBZGRUaW1lICU+JSBmaWx0ZXIoZGVwdGggPj0gMjUwICYgZGVwdGggPD01MDAgJiBwcm9qZWN0ID09ICJFVE5QIikpCgpzdW1tYXJ5KERGRzEpCnN1bW1hcnkoREZHMikKc3VtbWFyeShERkczKQoKc3VtbWFyeShERkcxKSRyLnNxIC0gc3VtbWFyeShERkcyKSRyLnNxCnN1bW1hcnkoREZHMikkci5zcSAtIHN1bW1hcnkoREZHMykkci5zcQpzdW1tYXJ5KERGRzMpJHIuc3EKYGBgCnBuZyhmaWxlbmFtZSA9ICIuL2ZpZ3VyZXMvQ29tYmluZWRQMkluZm8ucG5nIiwgd2lkdGggPSAxMCwgaGVpZ2h0ID0gOCwgdW5pdHMgPSAiaW4iLCByZXMgPSAyMDApClN0YXRpb25JbmZvUGxvdCgpCmRldi5vZmYoKQpgYGB7ciBmaWcuaGVpZ2h0ID0gOCwgZmlnLndpZHRoID0gMTB9CiNwbG90Lm5ldygpCkZsdXhHYW1QbG90IDwtIGZ1bmN0aW9uKCl7CiAgcGFyKG1mcm93ID0gYygyLDIpKQogIHBsb3QoREZHMSkKICBtdGV4dChleHByZXNzaW9uKGJvbGQoIkMiKSksIHNpZGUgPSAzLCBsaW5lID0gMCwgYWRqID0gMCwgY2V4ID0gMikKICBwYXIobWZnID0gYygxLDEpKQogIG10ZXh0KGV4cHJlc3Npb24oYm9sZCgiQSIpKSwgc2lkZSA9IDMsIGxpbmUgPSAwLCBhZGogPSAwLCBjZXggPSAyKQogIHBhcihtZmcgPSBjKDEsMikpCiAgbXRleHQoZXhwcmVzc2lvbihib2xkKCJCIikpLCBzaWRlID0gMywgbGluZSA9IDAsIGFkaiA9IDAsIGNleCA9IDIpCn0KCkZsdXhHYW1QbG90KCkKCnBuZyhmaWxlbmFtZSA9ICIuL2ZpZ3VyZXMvRmx1eEdhbVBsb3QucG5nIiwgd2lkdGggPSAxMCwgaGVpZ2h0ID0gOCwgdW5pdHMgPSAiaW4iLCByZXMgPSAyMDApCkZsdXhHYW1QbG90KCkKZGV2Lm9mZigpCmBgYAoKQ2hlY2sgb2YgYWN0dWFsIGRhdGEgZm9yIGhvdXIKYGBge3J9CmdncGxvdChkYXRhID0gYmRzICU+JSBmaWx0ZXIoZGVwdGggPj0gMTc1LCBkZXB0aCA8PSA1MDApLCBhZXMoeSA9IERGL0RaLCB4ID0gaG91cih0aW1lKSwgY29sID0gZGVwdGgsIGdyb3VwID0gZGVwdGgpKSArIGdlb21fcG9pbnQoKSArIGdlb21fbGluZSgpCmBgYAoKCiNPc3BzCgoodSBtb2wgQyAvIG1eMyAvIGRheSkKYGBge3IgZmlnLndpZHRoID0gNiwgZmlnLmhlaWdodCA9IDR9CmRpc2FnRmlnIDwtIGJkcyAlPiUgZmlsdGVyKHByb2plY3QgPT0gIkVUTlAiKSAlPiUKICBnZ3Bsb3QoYWVzKHkgPSBkZXB0aCwgeCA9IHByYWNtYTo6bnRocm9vdChvc3BzRFosIDMpLCBzaGFwZSA9IGZhY3RvcihkYXkodGltZSkpLCBmaWxsID0gaG91cih0aW1lKSwgZ3JvdXAgPSBmYWN0b3IodGltZSkpKSArIGdlb21fcG9pbnQoc2l6ZSA9IDIpICsgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTAwMCwgMCkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtMSwgMSkpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwKSArICAgc2NhbGVfc2hhcGVfbWFudWFsKG5hbWUgPSAiRGF5IG9mIE1vbnRoIiwgdmFsdWVzID0gcmVwKDIxOjI1LCAyKSkgKwogICNsYWJzKHggPSBicXVvdGUoIk9ic2VydmVkIC0gTW9kZWxlZCBTbWFsbCBQYXJ0aWNsZSBGbHV4In4ozrxtb2wvbV4zL2RheSkpLCB5ID0gIkRlcHRoIChtKSIpICsKICBsYWJzKHggPSBwYXN0ZSgiRGV2aWF0aW9uIGZyb20gTW9kZWwiLCBleHByZXNzaW9uKCjOvG1vbC9tXjMvZGF5KSkpKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4obmFtZSA9ICJIb3VyIG9mIERheSIsIGJyZWFrcyA9IGMoMCwgNiwgMTIsIDE4LCAyNCksIGNvbG9ycyA9IGMoImJsYWNrIiwgImJsdWUiLCAid2hpdGUiLCAib3JhbmdlIiwgImJsYWNrIikpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMTc1LCBjb2xvciA9ICJkYXJrZ3JlZW4iKSArIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDg1MCwgY29sb3IgPSAiZGFya2JsdWUiKQpkaXNhZ0ZpZwojZ2dzYXZlKCIuLmZpZ3VyZXMvRmx1eFNpemVTaGlmdC5zdmciCgogZ2dzYXZlKCJmaWd1cmVzL0ZsdXhTaXplU2hpZnQucG5nIikKIGdnc2F2ZSgiZmlndXJlcy9GbHV4U2l6ZVNoaWZ0LnN2ZyIpCmBgYAoKIyMjIENsYXJhIEZpZwpGb3IgTlNGIFByb3Bvc2FsCnBsb3RfZ3JpZCgKICBQbG90UGFydGljbGVzbWFueSwKICBQbG90UFNEbWFueSwKICByZWxfd2lkdGhzID0gYygyLCAzKQogICkKYGBge3IgZmlnLmhlaWdodCA9IDgsIGZpZy53aWR0aCA9IDEwfQoKcGdUb3AgPC0gZ2dkcmF3KHBsdEZseE5vTGVnZW5kIAogICAgICAgKSArCiAgZHJhd19wbG90KHBsdEZseFpvb20sIC40LCAuMjUsIC41NSwgLjYwKSArCiAgZHJhd19wbG90X2xhYmVsKAogICAgYygiIiwiRCIpLAogICAgYyguMDUsIDAuNTUpLAogICAgYygxLCAwLjg1KSwKICAgIHNpemUgPSAxNgogICkKCnBnQ0YgPC0gcGxvdF9ncmlkKFBsb3RQYXJ0aWNsZXNtYW55ICsgeWxpbShjKDEwMDAsIDApKSwKICAgICAgICAgICAgICAgICAgUGxvdFBTRG1hbnkgKyB5bGltKGMoMTAwMCwgMCkpICt0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpLAogICAgICAgICAgICAgICAgICBwZ1RvcCArIHRoZW1lKHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCB1bml0cyA9ICJjbSIpKSwKICAgICAgICAgICAgICAgICAgICBkaXNhZ0ZpZyArIHRoZW1lKHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIC4yLCAwKSwgdW5pdHMgPSAiY20iKSksCiAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDIsIHJlbF9oZWlnaHRzID0gYyg0LCA0KSwgbGFiZWxzID0gYygiQSIsICJCIiwgIkMiLCAiRSIpLCBsYWJlbF9zaXplID0gMTYpCnBnQ0YKCmdnc2F2ZSgiLi9maWd1cmVzL1VWUF9mb3Jfem9vcF9wcm9wb3NhbC5wbmciLCBwZ0NGLCB3aWR0aCA9IDEwLCBoZWlnaHQgPSA4LCB1bml0cyA9ICJpbiIpCmBgYAoKYGBge3J9CmJkc0FkZFRpbWUgPC0gYmRzICU+JQogIG11dGF0ZShIb3VyID0gaG91cih0aW1lKSwgRGF5ID0gZGF5KHRpbWUpKQoKT1pHMSA8LSBnYW0ob3Nwc0RaIH4gcyhkZXB0aCwgayA9IDMpICsgcyhEYXksIGsgPSAzKSArIHMoSG91ciwgayA9IDQsIGJzID0gImNjIiksIGtub3RzID0gbGlzdChIb3VyID0gYygwLCAyNCkpLCBkYXRhID0gYmRzQWRkVGltZSAlPiUgZmlsdGVyKGRlcHRoID49IDE3NSAmIGRlcHRoIDw9NTAwICYgcHJvamVjdCA9PSAiRVROUCIpKQoKT1pHMiA8LSBnYW0ob3Nwc0RaIH4gcyhkZXB0aCwgayA9IDMpICsgcyhEYXksIGsgPSAzKSwgZGF0YSA9IGJkc0FkZFRpbWUgJT4lIGZpbHRlcihkZXB0aCA+PSAxNzUgJiBkZXB0aCA8PTUwMCAmIHByb2plY3QgPT0gIkVUTlAiKSkKCk9aRzMgPC0gZ2FtKG9zcHNEWiB+IHMoZGVwdGgsIGsgPSAzKSwgZGF0YSA9IGJkc0FkZFRpbWUgJT4lIGZpbHRlcihkZXB0aCA+PSAxNzUgJiBkZXB0aCA8PTUwMCAmIHByb2plY3QgPT0gIkVUTlAiKSkKCnN1bW1hcnkoT1pHMSkKc3VtbWFyeShPWkcyKQpzdW1tYXJ5KE9aRzMpCgpzdW1tYXJ5KE9aRzEpJHIuc3EgLSBzdW1tYXJ5KE9aRzIpJHIuc3EKc3VtbWFyeShPWkcyKSRyLnNxIC0gc3VtbWFyeShPWkczKSRyLnNxCnN1bW1hcnkoT1pHMykkci5zcQpgYGAKCmBgYHtyfQpPU01TR2FtUGxvdCA8LSBmdW5jdGlvbigpewogIHBhcihtZnJvdyA9IGMoMSwyKSkKICBwbG90KE9aRzIpCiAgbXRleHQoZXhwcmVzc2lvbihib2xkKCJCIikpLCBzaWRlID0gMywgbGluZSA9IDAsIGFkaiA9IDAsIGNleCA9IDIpCiAgcGFyKG1mZyA9IGMoMSwxKSkKICBtdGV4dChleHByZXNzaW9uKGJvbGQoIkEiKSksIHNpZGUgPSAzLCBsaW5lID0gMCwgYWRqID0gMCwgY2V4ID0gMikKfQoKT1NNU0dhbVBsb3QoKQoKcG5nKGZpbGVuYW1lID0gIi4vZmlndXJlcy9PU01TR2FtUGxvdC5wbmciLCB3aWR0aCA9IDEwLCBoZWlnaHQgPSA2LCB1bml0cyA9ICJpbiIsIHJlcyA9IDIwMCkKT1NNU0dhbVBsb3QoKQoKZGV2Lm9mZigpCmBgYAoKYGBge3J9CnBsb3QoT1pHMikKYGBgCgoKYGBge3J9CmJkcyAlPiUgZmlsdGVyKHByb2plY3QgPT0gIlAxNiIpICU+JQogIGdncGxvdChhZXMoeSA9IGRlcHRoLCB4ID0gb3Nwc0RaKSkgKyBmYWNldF93cmFwKH5wcm9qZWN0KSArIGdlb21fcG9pbnQoKSArIHNjYWxlX3lfcmV2ZXJzZShsaW1pdHMgPSBjKDUwMCwgMCkpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCkKYGBgCgojIFRyYXAgZGF0YQpgYGB7cn0KdHJhcEZsdXgzIDwtIHJlYWRfY3N2KCJkYXRhT3V0L2ZsdXhNU19kaXN0aWxsZWQuY3N2IikKVVZQRmx1eENvbWIgPC0gcmVhZF9jc3YoImRhdGFPdXQvQ29tYmluZWRQcm9maWxlRmx1eEVzdF9EUy5jc3YiKQpVVlBGbHV4T0UgPC0gcmVhZF9jc3YoImRhdGFPdXQvT2JzZXJ2ZWRWc0V4cGVjdGVkRmx1eC5jc3YiKQoKYGBgCgpgYGB7cn0KdHJhcEZsdXgzCmBgYApgYGB7cn0KVVZQRmx1eENvbWIKYGBgCgoKYGBge3J9CgpmbHV4TVNfZGlzdGlsbGVkX3RvUGxvdCA8LSB0cmFwRmx1eDMgJT4lCiAgbXV0YXRlKFNhbXBsZVR5cGUgPSByZWNvZGUoU2FtcGxlVHlwZSwgYHBsdXMucGAgPSAicGx1cy1wYXJ0aWNsZXMiLCB0b3AgPSAidG9wLWNvbGxlY3RvciIpKQpgYGAKClJlbW92ZSB0cmFwcyB3aGVyZSBtYXNzIHNwZWMgZGlkbid0IHdvcmsgY29ycmVjdGx5CjItMTcgMTUwCjEtMTIgNzNtCjEtMTIgMTQ4CjItMTQgMTAwCnwoVHJhcElEID09ICIyLTE3IiAmIERlcHRoID09IDE1MCkKYGBge3J9CmZsdXhNU19kaXN0aWxsZWRfdG9QbG90MiA8LSBmbHV4TVNfZGlzdGlsbGVkX3RvUGxvdCAlPiUKIGZpbHRlcighKChUcmFwSUQgPT0gIjEtMTIiKSB8IChUcmFwSUQgPT0gIjItMTQiICYgRGVwdGggPT0gMTAwKXwoVHJhcElEID09ICIyLTE3IiAmIERlcHRoID09IDE1MCkpKQpmbHV4TVNfZGlzdGlsbGVkX3RvUGxvdDIKYGBgCgpgYGB7cn0KIyBVVlBGbHV4Q29tYiAlPiUKIyAgIGdncGxvdChhZXMoeSA9IGRlcHRoKSkgICsgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTAwMCwgMCkpICsKIyAgIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDIwMCkpICsKIyAgIGdlb21fcG9pbnQoYWVzKHkgPSBEZXB0aCwgeCA9IENfZmx1eF91bW9sLCBmaWxsID0gU2FtcGxlVHlwZSwgc2hhcGUgPSBUcmFwVHlwZSksCiMgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIHN0cm9rZSA9IDEsIHNpemUgPSA1LCBkYXRhID0gZmx1eE1TX2Rpc3RpbGxlZF90b1Bsb3QpICsKIyAgIGdlb21fcG9pbnQoYWVzKHggPSBGbHV4KSwgc2l6ZSA9IDMsIHNoYXBlID0gMjEsIGNvbG9yID0gIndoaXRlIiwgZmlsbCA9ICJibGFjayIpICsKIyAgIGdlb21fcG9pbnQoYWVzKHggPSAtMSwgeSA9IC0xLCBzaXplID0gIlVWUCIpKSArICMgZHVtbXkgcG9pbnQgZm9yIHRoZSBsZWdlbmQKIyBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gYygyNSwgMjIpKSsKIyAgIHNjYWxlX3NpemVfbWFudWFsKHZhbHVlcyA9IDEsIG5hbWUgPSAiIikgKwojICAgeWxhYigiRGVwdGggKG0pIikgKyB4bGFiKCJGbHV4IMK1bW9sQy9tXjIvZGF5IikgKwojICAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChzaGFwZSA9IDIxKSkpICsKIyAgIHNjYWxlX2ZpbGxfdmlyaWRpc19kKCkgKwojICAgdGhlbWVfY293cGxvdCgpICsgCiMgICB0aGVtZSgKIyAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC41LCAwLjQpLAojICAgICAgICAgbGVnZW5kLmJveC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDAuNSksCiMgICAgICAgICBsZWdlbmQubWFyZ2luID0gbWFyZ2luKC0xMCwgNSwgMTAsIDUpCiMgICApICsKIyAgIGdlb21fcmVjdChkYXRhID0gZGF0YS5mcmFtZShwcm9qZWN0ID0gIkVUTlAiKSwgYWVzKHhtaW4gPSAxNSwgeG1heCA9IDMyLCB5bWluID0gNDUsIHltYXggPSAxOTUpLCBjb2xvdXIgPSAicmVkIiwgZmlsbCA9IE5BLCBpbmhlcml0LmFlcyA9IEZBTFNFKQojICBnZ3NhdmUoImZpZ3VyZXMvRml0dGVkRmx1eC5wbmciKQojICBnZ3NhdmUoImZpZ3VyZXMvRml0dGVkRmx1eC5zdmciKQpgYGAKClRyYXBzIHdoZXJlIG1hc3Mgc3BlYyBkaWRuJ3Qgd29yay4KCgpgYGB7cn0KVVZQRmx1eFBsb3QwMCA8LSBVVlBGbHV4Q29tYiAlPiUgCiAgZ2dwbG90KGFlcyh5ID0gZGVwdGgpKSAgKyBzY2FsZV95X3JldmVyc2UobGltaXRzID0gYygxMDAwLCAwKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDIwMCkpICsKICBnZW9tX3BvaW50KGFlcyh5ID0gRGVwdGgsIHggPSBDX2ZsdXhfdW1vbCwgc2hhcGUgPSBUcmFwVHlwZSwgSUQgPSBUcmFwSUQpLAogICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgc3Ryb2tlID0gMSwgc2l6ZSA9IDUsIGRhdGEgPSBmbHV4TVNfZGlzdGlsbGVkX3RvUGxvdDIpICsKICBnZW9tX2xpbmUoYWVzKHggPSBGbHV4KSwgc2l6ZSA9IDEsIGNvbG9yID0gImJsYWNrIikgKwogIGdlb21fcG9pbnQoYWVzKHggPSAtMSwgeSA9IC0xLCBzaXplID0gIlVWUCBFc3RpbWF0ZSIpKSArICMgZHVtbXkgcG9pbnQgZm9yIHRoZSBsZWdlbmQKICBnZW9tX3BvaW50KGFlcyh4ID0gdG90X2ZsdXgyKSwgc2l6ZSA9IDMsIHNoYXBlID0gMjEsIGNvbG9yID0gIndoaXRlIiwgZmlsbCA9ICJibGFjayIsIGRhdGEgPSBVVlBGbHV4T0UpICsKc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IGMoMjUsIDIyKSkrCiAgc2NhbGVfc2l6ZV9tYW51YWwodmFsdWVzID0gMSwgbmFtZSA9ICIiKSArCiAgeWxhYigiRGVwdGggKG0pIikgKwogICN4bGFiKGV4cHJlc3Npb24oRmx1eCDCtW1vbEMvbV4yL2RheSkpICsKICB4bGFiKGV4cHJlc3Npb24ocGFzdGUoInggYXhpcyAiLCByaW5nKEEpXjIpKSkgKwogIHhsYWIoZXhwcmVzc2lvbihwYXN0ZSgiRmx1eCAowrUgbW9sIEMvIiwgbV4yLCAiL2RheSkiKSkpICsKICAKICBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNoYXBlID0gMjEpKSkgKwogIHRoZW1lX2Nvd3Bsb3QoKSArIAogIHRoZW1lKAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC41LCAwLjQpLAogICAgICAgIGxlZ2VuZC5ib3guYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIHNpemUgPSAwLjUpLAogICAgICAgIGxlZ2VuZC5tYXJnaW4gPSBtYXJnaW4oLTEwLCA1LCAxMCwgNSkKICApIAojIFVWUEZsdXhQbG90IDwtIFVWUEZsdXhQbG90MDAgKwojICAgZ2VvbV9yZWN0KGRhdGEgPSBkYXRhLmZyYW1lKHByb2plY3QgPSAiRVROUCIpLCBhZXMoeG1pbiA9IDE1LCB4bWF4ID0gMzIsIHltaW4gPSA0NSwgeW1heCA9IDE5NSksIGNvbG91ciA9ICJyZWQiLCBmaWxsID0gTkEsIGluaGVyaXQuYWVzID0gRkFMU0UpCgpVVlBGbHV4UGxvdDAwCgpnZ3NhdmUoImZpZ3VyZXMvRml0dGVkRmx1eC5wbmciKQpnZ3NhdmUoImZpZ3VyZXMvRml0dGVkRmx1eC5zdmciKQpgYGAKCgojIyBFeGFtcGxlIHBhcnRpY2xlIHNpemUgZGlzdHJpYnV0aW9uCgpob3Jpem9udGFsR2FtUGxvdCA8LSBkYXRhR2FtSG9yaXpvbnRhbCAlPiUgZ2dwbG90KGFlcyh4ID0gcmVzcF9maXQsIHkgPSBkZXB0aCwgY29sID0gbG9nKGxiKSwgZ3JvdXAgPSBsYikpICsgc2NhbGVfeV9yZXZlcnNlKCkgKyBnZW9tX3BvaW50KCkgKyBzY2FsZV94X2xvZzEwKGxpbWl0cyA9IGMoMTBeLTgsIE5BKSkgKyBzY2FsZV9jb2xvcl92aXJpZGlzX2MoKSArIGdlb21fcGF0aCgpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMSkgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSA1KSAgKyBnZW9tX2Vycm9yYmFyKGFlcyh4bWluID0gcmVzcF9sb3dlciwgeG1heCA9IHJlc3BfdXBwZXIpLCB3aWR0aCA9IDEwLCBhbHBoYSA9IDAuNSkrIHRoZW1lX2J3KCkKCmBgYHtyIGZpZy53aWR0aD0gMTB9ClRQUGxvdCA8LSBiZXMgJT4lIGZpbHRlcihwcm9maWxlID09ICJzdG5fMDQzIikgJT4lIGdyb3VwX2J5KGxiKSAlPiUgZ2dwbG90KGFlcyh4ID0gVG90YWxQYXJ0aWNsZXMsIHkgPSBkZXB0aCwgY29sID0gbG9nKGxiKSwgZ3JvdXAgPSBsYikpICsgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTAwMCwgMCkpICsgZ2VvbV9wb2ludCgpICsgc2NhbGVfeF9sb2cxMCgpICsgc2NhbGVfY29sb3JfdmlyaWRpc19jKCkgKyBnZW9tX3BhdGgoKSArIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDEpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gNSkgKyBsYWJzKHkgPSAiRGVwdGggKG0pIiwgeCA9ICJUb3RhbFBhcnRpY2xlcyBPYnNlcnZlZCAoIykiKQoKbm5wUGxvdCA8LSBiZXMgJT4lIGZpbHRlcihwcm9maWxlID09ICJzdG5fMDQzIikgJT4lIGdyb3VwX2J5KGxiKSAlPiUgZ2dwbG90KGFlcyh4ID0gbl9ucGFydGljbGVzLCB5ID0gZGVwdGgsIGNvbCA9IGxvZyhsYiksIGdyb3VwID0gbGIpKSArIHNjYWxlX3lfcmV2ZXJzZShsaW1pdHMgPSBjKDEwMDAsIDApKSArIGdlb21fcG9pbnQoKSArIHNjYWxlX3hfbG9nMTAoKSArIHNjYWxlX2NvbG9yX3ZpcmlkaXNfYygpICsgZ2VvbV9wYXRoKCkgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAxKSArIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDUpICsgbGFicyh5ID0gIkRlcHRoIChtKSIsIHggPSAiQmluc2l6ZSBhbmQgVm9sdW1lIE5vcm1hbGl6ZWQgUGFydGljbGVzICgjL0wvbW0pIikKCkZpdFBsb3QgPC0gYmVzICU+JSBmaWx0ZXIocHJvZmlsZSA9PSAic3RuXzA0MyIpICU+JSBncm91cF9ieShsYikgJT4lIGdncGxvdChhZXMoeCA9IG5ucF9zbW9vdGgsIHhtaW4gPSBubnBfbG93ZXIsIHhtYXggPSBubnBfdXBwZXIsIHkgPSBkZXB0aCwgY29sID0gbG9nKGxiKSwgZ3JvdXAgPSBsYikpICsgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTAwMCwgMCkpICsgZ2VvbV9wb2ludCgpICsgc2NhbGVfeF9sb2cxMCgpICsgc2NhbGVfY29sb3JfdmlyaWRpc19jKCkgKyBnZW9tX3BhdGgoKSArIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDEpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gNSkgKyBsYWJzKHkgPSAiRGVwdGggKG0pIiwgeCA9ICJTbW9vdGhlZCAtIE5vcm1hbGl6ZWQgUGFydGljbGVzICgjL0wvbW0pIikgKyBnZW9tX2Vycm9yYmFyKHdpZHRoID0gMTAsIGFscGhhID0gMC41KQoKbnBMZWdlbmQgPC0gZ2V0X2xlZ2VuZChGaXRQbG90ICsgdGhlbWUobGVnZW5kLmJveC5tYXJnaW4gPSBtYXJnaW4oMCwgMCwgNDAsIDIwMCkpICsgbGFicyhjb2wgPSBleHByZXNzaW9uKGxvZ1tlXShTaXplIChtbSkpKSkpCgpwbG90X2dyaWQoCiAgVFBQbG90ICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSwKICBubnBQbG90ICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSwKICBucExlZ2VuZCAsCiAgRml0UGxvdCArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKKQoKZ2dzYXZlKCJmaWd1cmVzL0FsbFBhcnRpY2xlU2l6ZXMuc3ZnIikKZ2dzYXZlKCJmaWd1cmVzL0FsbFBhcnRpY2xlU2l6ZXMucG5nIikKYGBgCgoKIyMgV2ViZXIgQmlhbmNoaSBGaWdzCgoKCgpgYGB7cn0KU2FtZUdhbSA8LSBnYW0oVG90YWxQYXJ0aWNsZXMgfnMobG9nKGxiKSwgbG9nKGRlcHRoKSwgYnkgPSBmYWN0b3IodGltZSkpLCBvZmZzZXQgPSBsb2codm9sICogYmluc2l6ZSksIGZhbWlseSA9IG5iKCksCiAgICBkYXRhID0gYmVzICU+JSBmaWx0ZXIocHJvamVjdCA9PSAiRVROUCIpKQpgYGAKCmBgYHtyfQpiZXNFIDwtIGJlcyAlPiUgZmlsdGVyKHByb2plY3QgPT0gIkVUTlAiKQoKbGJfbmV3IDwtIGV4cChzZXEoZnJvbSA9IGxvZygwLjEpLCB0byA9IGxvZygyLjEpLCBieSA9IDAuMDUpKQp1Yl9uZXcgPC0gbGVhZChsYl9uZXcpCmJpbnNpemVfbmV3IDwtIHViX25ldyAtIGxiX25ldwoKbGJicyA8LSB0aWJibGUobGIgPSBsYl9uZXcsIHViID0gdWJfbmV3LCBiaW5zaXplID0gYmluc2l6ZV9uZXcpCgpFeHBhbmRlZCA8LSBleHBhbmRfZ3JpZChsYiA9IGV4cChzZXEoZnJvbSA9IGxvZygwLjEpLCB0byA9IGxvZygyKSwgYnkgPSAwLjA1KSksIGRlcHRoID0gc2VxKGZyb20gPSAyMCwgdG8gPSAyMDAwLCBieSA9IDIwKSwgdGltZSA9IGFzLmZhY3Rvcih1bmlxdWUoYmVzRSR0aW1lKSkpICU+JSBsZWZ0X2pvaW4obGJicywgYnkgPSAibGIiKQoKUHJlZCA8LSBleHAocHJlZGljdChTYW1lR2FtLCBFeHBhbmRlZCkpClRvUGxvdCA8LSBiaW5kX2NvbHMoRXhwYW5kZWQsIG5ucGFydGljbGVzID0gUHJlZCkgJT4lIG11dGF0ZSh0aW1lID0gYXMuY2hhcmFjdGVyKHRpbWUpKSAlPiUgbXV0YXRlKG5wYXJ0aWNsZXMgPSBubnBhcnRpY2xlcyAqIGJpbnNpemUpCmBgYAoKYGBge3J9ClRvUGxvdCAlPiUgZmlsdGVyKGxiIDw9IDIpICU+JSAgZ2dwbG90KGFlcyh4ID0gbGIsIHkgPSBkZXB0aCwgZmlsbCA9IGxvZzEwKG5ucGFydGljbGVzKSwgeiA9IGxvZzEwKG5ucGFydGljbGVzKSkpICsgZ2VvbV90aWxlKCkgKyBzY2FsZV9maWxsX3ZpcmlkaXNfYygpICsgc2NhbGVfeV9yZXZlcnNlKCkgKyBzY2FsZV94X2xvZzEwKCkgICsgZmFjZXRfd3JhcCh+dGltZSkgKyBnZW9tX2NvbnRvdXIoY29sb3IgPSAiYmxhY2siKQpgYGAKYGBge3J9Cm1lYW5CZXNlIDwtIFRvUGxvdCAlPiUgZmlsdGVyKGxiIDw9IDIpICU+JSBncm91cF9ieShsYiwgZGVwdGgpICU+JSBzdW1tYXJpemUobnBhcnRpY2xlcyA9IG1lYW4obnBhcnRpY2xlcyksIG5ucGFydGljbGVzID0gbWVhbihubnBhcnRpY2xlcykpCgpXQkNvbG9yTWFwIDwtIG1lYW5CZXNlJT4lCiAgIGdncGxvdChhZXMoeCA9IGxiLCB5ID0gZGVwdGgsIGZpbGwgPSBsb2cxMChubnBhcnRpY2xlcyksIHogPSBsb2cxMChubnBhcnRpY2xlcykpKSArIGdlb21fdGlsZSgpICsgc2NhbGVfZmlsbF92aXJpZGlzX2MobmFtZSA9ICJsb2cxMChudW1iZXIgZGVuc2l0eSBcbiAobm9ybWFsaXplZCkpIikgKyBzY2FsZV95X3JldmVyc2UoKSArIHNjYWxlX3hfbG9nMTAoKSArIGdlb21fY29udG91cihjb2xvciA9ICJibGFjayIpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMTYwLCBjb2xvciA9ICJkYXJrZ3JlZW4iKSArIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDg1MCwgY29sb3IgPSAiZGFya2JsdWUiKQpXQkNvbG9yTWFwCmBgYApBdmVyYWdlIG9mIGV2ZXJ5dGhpbmcKCmBgYHtyfQojbWVhbkJlc2UwNDMgPC0gVG9QbG90ICU+JSBmaWx0ZXIobGIgPD0gMiwgdGltZSA9PSAiMjAxNy0wMS0xMyAxMTo1MTozMSIpCgptZWFuQmVzZSU+JQogICBnZ3Bsb3QoYWVzKHggPSBsYiwgeSA9IGRlcHRoLCBmaWxsID0gbG9nMTAobm5wYXJ0aWNsZXMpLCB6ID0gbG9nMTAobm5wYXJ0aWNsZXMpKSkgKyBnZW9tX3RpbGUoKSArIHNjYWxlX2ZpbGxfdmlyaWRpc19jKCkgKyBzY2FsZV95X3JldmVyc2UoKSArIHNjYWxlX3hfbG9nMTAoKSArIGdlb21fY29udG91cihjb2xvciA9ICJibGFjayIpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMTYwLCBjb2xvciA9ICJkYXJrZ3JlZW4iKQpgYGAKSnVzdCAwNDMKCmBgYHtyfQptYkdhbSA8LSBtZWFuQmVzZSAlPiUgZ3JvdXBfYnkoZGVwdGgpICAlPiUgbmVzdCgpICU+JQogIG11dGF0ZShtb2QgPSBtYXAoZGF0YSwgfmdhbShsb2cobm5wYXJ0aWNsZXMpIH4gbG9nKGxiKSwgZmFtaWx5ID0gZ2F1c3NpYW4oKSwgZGF0YSA9IC4pKSkgJT4lIAogIG11dGF0ZShwc2QgPSBtYXBfZGJsKG1vZCwgfnN1bW1hcnkoLikkcC5jb2VmZlsyXSkpCmBgYAoKYGBge3J9Cm1iR2FtICU+JSBnZ3Bsb3QoYWVzKHggPSBwc2QsIHkgPSBkZXB0aCkpICsgZ2VvbV9wYXRoKCkgKyBzY2FsZV95X3JldmVyc2UoKSArIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDE2MCwgY29sb3IgPSAiZGFya2dyZWVuIikgKyBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAgODUwLCBjb2xvciA9ICJkYXJrYmx1ZSIpCmBgYAoKCm1iR2FtIDwtIG1lYW5CZXNlMDQzICU+JSBncm91cF9ieShkZXB0aCkgICU+JSBuZXN0KCkgJT4lCiAgbXV0YXRlKG1vZCA9IG1hcChkYXRhLCB+Z2FtKGxvZyhubnBhcnRpY2xlcykgfiBsb2cobGIpLCBmYW1pbHkgPSBnYXVzc2lhbigpLCBkYXRhID0gLikpKSAlPiUgCiAgbXV0YXRlKHBzZCA9IG1hcF9kYmwobW9kLCB+c3VtbWFyeSguKSRwLmNvZWZmWzJdKSkKCgpgYGB7cn0KcFdCUFNEIDwtIG1iR2FtICU+JSBnZ3Bsb3QoYWVzKHggPSBwc2QsIHkgPSBkZXB0aCkpICsgZ2VvbV9wYXRoKCkgKyBzY2FsZV95X3JldmVyc2UoKSAgKyBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAxNjAsIGNvbG9yID0gImRhcmtncmVlbiIpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gIDg1MCwgY29sb3IgPSAiZGFya2JsdWUiKQpwV0JQU0QKYGBgCgoKIyMgRmlnIDUgV0IKCmJkcyAlPiUgZmlsdGVyKHByb2ZpbGUgPT0gInN0bl8wNDMiLCBkZXB0aCA8PSAyMDAwKSAlPiUgZ2dwbG90KGFlcyh4ID0gcHNkX2dhbSwgeG1pbiA9IHBzZF9nYW0gLSBwc2Rfc2VnICogMiwgeG1heCA9IHBzZF9nYW0gKyBwc2Rfc2VnICogMiwgeSA9IGRlcHRoKSkgKyBnZW9tX3BhdGgoc2l6ZSA9IDEpICsgc2NhbGVfeV9yZXZlcnNlKCkgKyBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAxNzUsIGNvbG9yID0gImRhcmtncmVlbiIpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gOTUwLCBjb2xvciA9ICJkYXJrYmx1ZSIpICsgZ2VvbV9yaWJib24oYWxwaGEgPSAwLjIpICsgbGFicyh4ID0gIlBTRCBzbG9wZSIpCgpBbGwgb2YgdGhlbQoKYGBge3J9CmJkcyAlPiUgZmlsdGVyKHByb2ZpbGUgPT0gInN0bl8wNDMiLCBkZXB0aCA8PSAyMDAwKSAlPiUgZ2dwbG90KGFlcyh4ID0gcHNkX2dhbSwgeG1pbiA9IHBzZF9nYW0gLSBwc2Rfc2VnICogMiwgeG1heCA9IHBzZF9nYW0gKyBwc2Rfc2VnICogMiwgeSA9IGRlcHRoKSkgKyBnZW9tX3BhdGgoc2l6ZSA9IDEpICsgc2NhbGVfeV9yZXZlcnNlKCkgKyBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAxNzUsIGNvbG9yID0gImRhcmtncmVlbiIpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gOTUwLCBjb2xvciA9ICJkYXJrYmx1ZSIpICsgZ2VvbV9yaWJib24oYWxwaGEgPSAwLjIpICsgbGFicyh4ID0gIlBTRCBzbG9wZSIpCmBgYAowNDMgb25seQoKYGBge3J9CmJkcyAlPiUgZmlsdGVyKHByb2ZpbGUgPT0gInN0bl8wNDMiLCBkZXB0aCA8PSAyMDAwLCBkZXB0aCA+IDE3NSkgJT4lIGdncGxvdChhZXMoeCA9IHNtYWxsX2Jpb3ZvbHVtZSwgeSA9IGRlcHRoKSkgKyBnZW9tX3BhdGgoc2l6ZSA9IDEpICsgc2NhbGVfeV9yZXZlcnNlKCkgKyBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAxNzUsIGNvbG9yID0gImRhcmtncmVlbiIpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gOTUwLCBjb2xvciA9ICJkYXJrYmx1ZSIpICsgZ2VvbV9wb2ludCgpCmBgYAoKYGBge3J9CnViRGYwIDwtIFRvUGxvdCAlPiUgbXV0YXRlKHViaW9tYXNzID0gbnBhcnRpY2xlcyAqIGxiIF4gYWdfZ2xvYmFsKQp1YkRmIDwtIHViRGYwICU+JSBncm91cF9ieSh0aW1lLCBkZXB0aCkgJT4lIHN1bW1hcml6ZSh1YmlvbWFzcyA9IHN1bSh1YmlvbWFzcykpICU+JSB1bmdyb3VwICU+JSBncm91cF9ieShkZXB0aCkKcGhvdGljQmlvbWFzcyA8LSB1YkRmICU+JSBmaWx0ZXIoZGVwdGggPD0gMTgwLCBkZXB0aCA+PSAxNjApICU+JSBzdW1tYXJpemUodWJpb21hc3MgPSBtZWFuKHViaW9tYXNzKSkgJT4lIHB1bGwodWJpb21hc3MpCnViRGYgPC0gdWJEZiAlPiUgbXV0YXRlKG5iaW9tYXNzID0gdWJpb21hc3MvcGhvdGljQmlvbWFzcykKdWJEZiAlPiUgZ2dwbG90KGFlcyh4ID0gbmJpb21hc3MsIHkgPSBkZXB0aCAsIGdyb3VwID0gdGltZSwgY29sID0gdGltZSkpICsgZ2VvbV9wYXRoKCkgKyBzY2FsZV95X3JldmVyc2UoKSArIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsMSkpCmBgYAoKCiAKYGBge3J9CnViRGYgPC0gVG9QbG90ICU+JSBtdXRhdGUodWJpb21hc3MgPSBucGFydGljbGVzICogbGIgXiBhZ19nbG9iYWwpICU+JSBncm91cF9ieSh0aW1lLCBkZXB0aCkgJT4lIHN1bW1hcml6ZSh1YmlvbWFzcyA9IHN1bSh1YmlvbWFzcykpICU+JSB1bmdyb3VwICU+JSBncm91cF9ieShkZXB0aCkgICU+JSBzdW1tYXJpc2UodWJpb21hc3MgPSBtZWFuKHViaW9tYXNzKSkKcGhvdGljQmlvbWFzcyA8LSB1YkRmICU+JSBmaWx0ZXIoZGVwdGggPD0gMTgwLCBkZXB0aCA+PSAxNjApICU+JSBzdW1tYXJpemUodWJpb21hc3MgPSBtZWFuKHViaW9tYXNzKSkgJT4lIHB1bGwodWJpb21hc3MpCnViRGYgPC0gdWJEZiAlPiUgbXV0YXRlKG5iaW9tYXNzID0gdWJpb21hc3MvcGhvdGljQmlvbWFzcykKdWJEZiAlPiUgZ2dwbG90KGFlcyh4ID0gbmJpb21hc3MsIHkgPSBkZXB0aCkpICsgZ2VvbV9wYXRoKCkgKyBzY2FsZV95X3JldmVyc2UoKSArIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsMSkpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMTc1LCBjb2xvciA9ICJkYXJrZ3JlZW4iKQpgYGAKCgojIyMgU21hbGwgcGFydGljbGVzIGJpb21hc3MKCmBgYHtyfQpQdWJEZiA8LSBUb1Bsb3QgJT4lIG11dGF0ZSh1YmlvbWFzcyA9IG5wYXJ0aWNsZXMgKiBsYiBeIGFnX2dsb2JhbCkgJT4lIGZpbHRlcihsYiA8IDAuNSkgJT4lIGdyb3VwX2J5KHRpbWUsIGRlcHRoKSAlPiUgc3VtbWFyaXplKHViaW9tYXNzID0gc3VtKHViaW9tYXNzKSkgJT4lIHVuZ3JvdXAgJT4lIGdyb3VwX2J5KGRlcHRoKSAgJT4lIHN1bW1hcmlzZSh1YmlvbWFzcyA9IG1lYW4odWJpb21hc3MpKQpwaG90aWNCaW9tYXNzIDwtIFB1YkRmICU+JSBmaWx0ZXIoZGVwdGggPD0gMTY1LCBkZXB0aCA+PSAxNTUpICU+JSBzdW1tYXJpemUodWJpb21hc3MgPSBtZWFuKHViaW9tYXNzKSkgJT4lIHB1bGwodWJpb21hc3MpClB1YkRmIDwtIFB1YkRmICU+JSBtdXRhdGUobmJpb21hc3MgPSB1YmlvbWFzcy9waG90aWNCaW9tYXNzKQpwV0JTIDwtIFB1YkRmICU+JSBnZ3Bsb3QoYWVzKHggPSBuYmlvbWFzcywgeSA9IGRlcHRoKSkgKyBnZW9tX3BhdGgoKSArIHNjYWxlX3lfcmV2ZXJzZSgpICsgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwxLjIpKSArIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDE2MCwgY29sb3IgPSAiZGFya2dyZWVuIikgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAxLCBjb2xvciA9ICJncmF5NTAiKSArIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGNvbG9yID0gImdyYXk1MCIpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gODUwLCBjb2xvciA9ICJkYXJrYmx1ZSIpICsgbGFicyggeCA9ICJTbWFsbCBwYXJ0aWNsZSBtYXNzIChub3JtLikiKQpwV0JTCmBgYAoKYGBge3J9Ckx1YkRmIDwtIFRvUGxvdCAlPiUgbXV0YXRlKHViaW9tYXNzID0gbnBhcnRpY2xlcyAqIGxiIF4gYWdfZ2xvYmFsKSAlPiUgZmlsdGVyKGxiID49IDAuNSkgJT4lIGdyb3VwX2J5KHRpbWUsIGRlcHRoKSAlPiUgc3VtbWFyaXplKHViaW9tYXNzID0gc3VtKHViaW9tYXNzKSkgJT4lIHVuZ3JvdXAgJT4lIGdyb3VwX2J5KGRlcHRoKSAgJT4lIHN1bW1hcmlzZSh1YmlvbWFzcyA9IG1lYW4odWJpb21hc3MpKQpwaG90aWNCaW9tYXNzIDwtIEx1YkRmICU+JSBmaWx0ZXIoZGVwdGggPD0gMTY1LCBkZXB0aCA+PTE1NSkgJT4lIHN1bW1hcml6ZSh1YmlvbWFzcyA9IG1lYW4odWJpb21hc3MpKSAlPiUgcHVsbCh1YmlvbWFzcykKTHViRGYgPC0gTHViRGYgJT4lIG11dGF0ZShuYmlvbWFzcyA9IHViaW9tYXNzL3Bob3RpY0Jpb21hc3MpCnBXQkwgPC0gTHViRGYgJT4lIGdncGxvdChhZXMoeCA9IG5iaW9tYXNzLCB5ID0gZGVwdGgpKSArIGdlb21fcGF0aCgpICsgc2NhbGVfeV9yZXZlcnNlKCkgKyBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLDEpKSArIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDE2MCwgY29sb3IgPSAiZGFya2dyZWVuIikgKyBsYWJzKCB4ID0gIkxhcmdlIHBhcnRpY2xlIG1hc3MgKG5vcm0uKSIpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMSwgY29sb3IgPSAiZ3JheTUwIikgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBjb2xvciA9ICJncmF5NTAiKSArIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDg1MCwgY29sb3IgPSAiZGFya2JsdWUiKQpwV0JMCmBgYAoKRm9yIHRvbSBhbmQgZGFuaWVsbGUKYGBge3J9CldCQ29sb3JNYXAKcFdCUFNECnBXQlMKcFdCTApgYGAKCmBgYHtyLCBmaWcud2lkdGggPSAxMCwgZmlnLmhlaWdodD0zfQpXQkZpZzUgPC0gcGxvdF9ncmlkKHBXQlBTRCwgcFdCUyxwV0JMLCBucm93ID0gMSwgbGFiZWxzID0gYygiQiIsICJDIiwgIkQiKSkKV0JGaWc1CmBgYAoKYGBge3IgZmlnLmhlaWdodCA9IDYsIGZpZy53aWR0aCA9IDh9CldCY29tYmluZWQgPC0gcGxvdF9ncmlkKFdCQ29sb3JNYXAgKyB0aGVtZShwbG90Lm1hcmdpbiA9IHVuaXQoYygwLDMsMCwgMyksICJjbSIpKSwgV0JGaWc1LCBuY29sID0gMSwgbGFiZWxzID0gYygiQSIsICIiKSkKV0Jjb21iaW5lZAoKZ2dzYXZlKCJmaWd1cmVzL1dCTW9kZWxWYWxpZGF0aW9uLnBuZyIpCmBgYAoKIyMgUDE2IEZsdXggCgpgYGB7ciBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD00fQpzY2llbnRpZmljXzEwIDwtIGZ1bmN0aW9uKHgpIHtwYXJzZSh0ZXh0PWdzdWIoImVcXCsqIiwgIiAlKiUgMTBeIiwgc2NhbGVzOjpzY2llbnRpZmljX2Zvcm1hdCgpKHgpKSkgfQojaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMTA3NjIyODcvaG93LWNhbi1pLWZvcm1hdC1heGlzLWxhYmVscy13aXRoLWV4cG9uZW50cy13aXRoLWdncGxvdDItYW5kLXNjYWxlcwojamFjb2JfbWFnbml0dWRlIDwtIGZ1bmN0aW9uKHgpe2V4cHJlc3Npb24oMTBecm91bmQobG9nMTAoeCkpKX0KCmNiMTAgPC0gYygnI2E2Y2VlMycsJyMxZjc4YjQnLCcjYjJkZjhhJywnIzMzYTAyYycsJyNmYjlhOTknLCcjZTMxYTFjJywnI2ZkYmY2ZicsJyNmZjdmMDAnLCcjY2FiMmQ2JywnIzZhM2Q5YScpCnBsdEZseFAxNiA8LSBiZHMgJT4lIGZpbHRlcihwcm9qZWN0ID09ICJQMTYiKSAlPiUgI2ZpbHRlcihERlAgPiAxKSAlPiUgI2ZpbHRlcihwcm9maWxlICVpbiUgYygic3RuXzA0MyIsICJwMTZuXzEwMCIpKSAlPiUKICBnZ3Bsb3QoYWVzKHkgPSBkZXB0aCwgeCA9IEZsdXhfU21vb3RoLCBncm91cCA9IGZhY3Rvcih0aW1lKSkpICArIGdlb21fcG9pbnQoc2l6ZSA9IDMsIHN0cm9rZSA9IDEpKwogIGdlb21fcGF0aCgpICsKICBzY2FsZV95X3JldmVyc2UobGltaXRzID0gYygxMDAwLCAwKSkrCiAgc2NhbGVfeF9sb2cxMChsaW1pdHMgPSBjKDM1LCAxNTApLGJyZWFrcyA9IHNlcShmcm9tID0gMjAsIHRvID0gMTUwLCBieSA9IDIwKSkgKwogICBzY2FsZV9jb2xvcl9ncmFkaWVudDIobG93ID0gImRhcmtncmVlbiIsIG1pZCA9ICJncmF5ODAiLCBoaWdoID0gInB1cnBsZSIsIG1pZHBvaW50ID0gMTApICsgc2NhbGVfc2hhcGVfbWFudWFsKG5hbWUgPSAiRGF5IG9mIE1vbnRoIiwgdmFsdWVzID0gcmVwKDIxOjI1LCAyKSkgKyAKICBzY2FsZV9maWxsX2dyYWRpZW50bihuYW1lID0gIkhvdXIgb2YgRGF5IiwgYnJlYWtzID0gYygwLCA2LCAxMiwgMTgsIDI0KSwgY29sb3JzID0gYygiYmxhY2siLCAiYmx1ZSIsICJ3aGl0ZSIsICJvcmFuZ2UiLCAiYmxhY2siKSkgKwogIApsYWJzKHggPSBicXVvdGUoU21vb3RoZWR+Rmx1eH4owrVtb2x+Qy9tXjIvZCkpLCB5ID0gIkRlcHRoIChtKSIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAyMDAsIGNvbG9yID0gImRhcmtncmVlbiIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IC4zKSwgbGVnZW5kLnNwYWNpbmcgPSB1bml0KC4xLCAiY20iKSkKIyAKIyAKIyAKIyBwbHRGbHhOb0xlZ2VuZCA8LSBwbHRGbHggKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCiMgcGx0Rmx4TGVnZW5kIDwtIGdldF9sZWdlbmQocGx0Rmx4KQojIApwbHRGbHhQMTYKIyAjcGxvdGx5OjpnZ3Bsb3RseShwbHQxKQpgYGAKCmBgYHtyIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTR9CmNiMTAgPC0gYygnI2E2Y2VlMycsJyMxZjc4YjQnLCcjYjJkZjhhJywnIzMzYTAyYycsJyNmYjlhOTknLCcjZTMxYTFjJywnI2ZkYmY2ZicsJyNmZjdmMDAnLCcjY2FiMmQ2JywnIzZhM2Q5YScpCnBsdERlbHRhM1AxNiA8LSBiZHMgJT4lIGZpbHRlcihwcm9qZWN0ID09ICJQMTYiKSAlPiUgI2ZpbHRlcihERlAgPiAxKSAlPiUgI2ZpbHRlcihwcm9maWxlICVpbiUgYygic3RuXzA0MyIsICJwMTZuXzEwMCIpKSAlPiUKICBnZ3Bsb3QoYWVzKHkgPSBkZXB0aCwgeCA9IHByYWNtYTo6bnRocm9vdChERi9EWiwgNSksIGdyb3VwID0gZmFjdG9yKHRpbWUpKSkgICsgZ2VvbV9wb2ludChzaXplID0gMywgc3Ryb2tlID0gMSkrCiAgZ2VvbV9wYXRoKCkgKwogIHNjYWxlX3lfcmV2ZXJzZShsaW1pdHMgPSBjKDEwMDAsIDApKSsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtMSwgLjEpLCBicmVha3MgPSBzZXEoZnJvbSA9IC0yLCB0byA9IC43NSwgYnkgPSAwLjUpKSArCiAgI3NjYWxlX3hfbG9nMTAoKSArCiAgIHNjYWxlX2NvbG9yX2dyYWRpZW50Mihsb3cgPSAiZGFya2dyZWVuIiwgbWlkID0gImdyYXk4MCIsIGhpZ2ggPSAicHVycGxlIiwgbWlkcG9pbnQgPSAxMCkgKyBzY2FsZV9zaGFwZV9tYW51YWwobmFtZSA9ICJEYXkgb2YgTW9udGgiLCB2YWx1ZXMgPSByZXAoMjE6MjUsIDIpKSArIAogIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKG5hbWUgPSAiSG91ciIsIGJyZWFrcyA9IGMoMCwgNiwgMTIsIDE4LCAyNCksIGNvbG9ycyA9IGMoImJsYWNrIiwgImJsdWUiLCAid2hpdGUiLCAib3JhbmdlIiwgImJsYWNrIikpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMjAwLCBjb2xvciA9ICJkYXJrZ3JlZW4iKSsKICBsYWJzKHggPSBicXVvdGUoKERGL0RaKV57MS81fX4owrVtb2xDL21eMy9kKV57MS81fSksIHkgPSAiRGVwdGggKG0pIikgKyB0aGVtZShsZWdlbmQucG9zID0gIm5vbmUiKQogICNsYWJzKHggPSAiKERGL0RaKSBeIDEvNSAowrVtb2wgQy9tXjMvZCkgXiAxLzUiKQoKcGx0RGVsdGEzUDE2CiNwbG90bHk6OmdncGxvdGx5KHBsdDFwb3MpCmBgYAoKYGBge3IgZmlnLndpZHRoID0gNiwgZmlnLmhlaWdodCA9IDR9Cm9zbXNfcDE2IDwtIGJkcyAlPiUgZmlsdGVyKHByb2plY3QgPT0gIlAxNiIpICU+JQogIGdncGxvdChhZXMoeSA9IGRlcHRoLCB4ID0gcHJhY21hOjpudGhyb290KG9zcHNEWiwgMyksIGdyb3VwID0gZmFjdG9yKHRpbWUpKSkgKyBnZW9tX3BvaW50KHNpemUgPSAzKSArIGdlb21fcGF0aCgpICsgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTAwMCwgMCkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtMSwgMSkpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwKSArICAgc2NhbGVfc2hhcGVfbWFudWFsKG5hbWUgPSAiRGF5IG9mIE1vbnRoIiwgdmFsdWVzID0gcmVwKDIxOjI1LCAyKSkgKyBsYWJzKHggPSAiT2JzZXJ2ZWQgLSBNb2RlbGVkIFNtYWxsIFBhcnRpY2xlIEZsdXggXG4gwrVtb2wvbV4zL2RheSIpICsKICBzY2FsZV9maWxsX2dyYWRpZW50bihuYW1lID0gIkhvdXIgb2YgRGF5IiwgYnJlYWtzID0gYygwLCA2LCAxMiwgMTgsIDI0KSwgY29sb3JzID0gYygiYmxhY2siLCAiYmx1ZSIsICJ3aGl0ZSIsICJvcmFuZ2UiLCAiYmxhY2siKSkgKyBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAxNzUsIGNvbG9yID0gImRhcmtncmVlbiIpIApwbG90bHk6OmdncGxvdGx5KG9zbXNfcDE2KQojZ2dzYXZlKCIuLmZpZ3VyZXMvRmx1eFNpemVTaGlmdC5zdmciCgpgYGAKCmBgYHtyIGZpZy53aWR0aCA9IDgsIGZpZy5oZWlnaHQ9OH0KcGxvdF9ncmlkKAogIHBsdEZseFAxNiwKICBwbHREZWx0YTNQMTYsCiAgb3Ntc19wMTYKKQoKZ2dzYXZlKCJmaWd1cmVzL1AxNkZsdXhSZWxhdGUuc3ZnIikKZ2dzYXZlKCJmaWd1cmVzL1AxNkZsdXhSZWxhdGUucG5nIikKYGBgCgojIEZsdXggYXR0ZW51YXRpb24gZXhhbXBsZQoKYGBge3J9CnNvdXJjZSgiTW9kZWxTdHVmZi5SIikKYGBgCgoKYGBge3J9CnNjYW5fZm9yX2V4YW1wbGUgPC0gYmRzICU+JSBmaWx0ZXIocHJvamVjdCA9PSAiRVROUCIsIGRlcHRoIDwgNTAwLCBkZXB0aCA+IDIwMCkgJT4lIHNlbGVjdChwcm9maWxlLCBkZXB0aCwgREZQLCB1c2VfdGhpc19ERlAsIG9zcHNEWikKCiNsb2Nfc3RhdGlvbiA9ICJzdG5fMDM2Igpsb2Nfc3RhdGlvbiA9ICJzdG5fMDQzIgpsb2NfZGVwdGggPSAyMjUKbG9jX3ByZXZfZGVwdGggPSAxMTIuNQoKYWxsREZQcyA8LSBiZHMgJT4lIGZpbHRlcihwcm9maWxlID09IGxvY19zdGF0aW9uLCBkZXB0aCA+PSBsb2NfcHJldl9kZXB0aCwgZGVwdGggPD0gbG9jX2RlcHRoKSAlPiUgc3VtbWFyaXplKERGUCA9IHByb2QoREZQKSwgdXNlX3RoaXNfREZQID0gcHJvZCh1c2VfdGhpc19ERlApKQoKbG9jX0RGUCA8LSAgYWxsREZQcyAlPiUgcHVsbChERlApCmxvY191c2VfREZQIDwtIGFsbERGUHMgJT4lIHB1bGwodXNlX3RoaXNfREZQKQoKCmZvcl9zaW5nbGVfZGlzYWcgPC0gYmVzICU+JSBmaWx0ZXIocHJvZmlsZSA9PSBsb2Nfc3RhdGlvbiwgZGVwdGggJWluJSBjKGxvY19wcmV2X2RlcHRoLCBsb2NfZGVwdGgpKSAlPiUgc2VsZWN0KGRlcHRoLCBsYiwgbm5wX3Ntb290aCkgJT4lCiAgbXV0YXRlKGRlcHRoID0gcmVjb2RlKGRlcHRoLCBgMTEyLjVgID0gIlNoYWxsb3ciLCBgMjI1YCA9ICJEZWVwIikpICU+JSAjIEkgaGF2ZSBubyBpZGVhIGhvdyB0byBub3QgaGFyZCBjb2RlIHRoaXMgYml0CiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IGRlcHRoLCB2YWx1ZXNfZnJvbSA9IG5ucF9zbW9vdGgpIAoKd2l0aF9kaXNhZyA8LSBmb3Jfc2luZ2xlX2Rpc2FnICU+JQogIG11dGF0ZShQcmVkaWN0ZWRfRGVlcCA9IHJlbWluX3Ntb290aF9zaHVmZmxlKFNoYWxsb3csIGxvY191c2VfREZQKSkgCiNyZW1pbl9zbW9vdGhfc2h1ZmZsZShmb3Jfc2luZ2xlX2Rpc2FnJFNoYWxsb3csbG9jX3VzZV9ERlApCgpmb3JfcGxvdF9kaXNhZyA8LSB3aXRoX2Rpc2FnICU+JSBwaXZvdF9sb25nZXIoY29scyA9IC1sYikgJT4lICNmaWx0ZXIobGIgPD0gNSkgJT4lCiAgbXV0YXRlKG5hbWUgPSBmYWN0b3IobmFtZSwgbGV2ZWxzID0gYygiU2hhbGxvdyIsICJEZWVwIiwgIlByZWRpY3RlZF9EZWVwIikpKSAlPiUKICBtdXRhdGUobmFtZSA9IHJlY29kZV9mYWN0b3IobmFtZSwgU2hhbGxvdyA9ICJTaGFsbG93ICgxMTIuNW0pIiwgRGVlcCA9ICJEZWVwICgyMjVtKSIsIFByZWRpY3RlZF9EZWVwID0gIlByZWRpY3RlZCBEZWVwICgyMjVtKSIpKQoKZm9yX3Bsb3RfZGlzYWcgJT4lIGdncGxvdChhZXMoeCA9IGxiLCB5ID0gdmFsdWUsIHNoYXBlID0gbmFtZSkpICsgZ2VvbV9wb2ludCgpICsgc2NhbGVfeF9sb2cxMCgpICsgc2NhbGVfeV9sb2cxMCgpICsgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IGMoMSwgNiwgMykpICsgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKSArIGxhYnMoeCA9ICJQYXJ0aWNsZSBTaXplIChtbSkiLCB5ID0gIk5vcm1hbGl6ZWQgUGFydGljbGUgQWJ1bmRhbmNlICgjL0wvbW0pIikKCmdnc2F2ZSgiZmlndXJlcy9EaXNhZ0V4YW1wbGUucG5nIikKZ2dzYXZlKCJmaWd1cmVzL0Rpc2FnRXhhbXBsZS5zdmciKQpgYGAKCgojIyBFSzYwCgpgYGB7cn0KZGF0YUJpbm5lZCA8LSByZWFkX2NzdigiZGF0YS9iYWNrc2NhdHRlcl90YWJsZV9nbzcuY3N2IikKYGBgCgpgYGB7cn0KZGF0YUJpbm5lZF8wMSA8LSBkYXRhQmlubmVkICU+JQogIG11dGF0ZSh0aW1lTWV4ID0gd2l0aF90eih0aW1lX2JpbiwgdHpvbmUgPSAiVVMvQ2VudHJhbCIpICkKYGBgCgpgYGB7cn0Kc3RhcnREYXkgPC0gZGF0YUJpbm5lZF8wMSR0aW1lTWV4ICU+JSBuYS5vbWl0ICU+JSBtaW4gJT4lIGZsb29yX2RhdGUodW5pdCA9ICJkYXlzIikKZW5kRGF5IDwtIGRhdGFCaW5uZWRfMDEkdGltZU1leCAlPiUgbmEub21pdCAlPiUgbWF4ICU+JSBjZWlsaW5nX2RhdGUodW5pdCA9ICJkYXlzIikKdGltZUJyZWFrcyA8LSBzZXEoZnJvbSA9IHN0YXJ0RGF5LCB0byA9IGVuZERheSwgYnkgPSAiMTIgaG91cnMiKQp0aW1lTGFiZWxzIDwtIGZvcm1hdCh0aW1lQnJlYWtzKQpgYGAKCgpgYGB7cn0KcGxvdExldHRlcnMgPC0gdHJpYmJsZSgKICB+bGV0dGVyLCB+ZGVwdGhfYmluLCB+dGltZU1leCwKICAiQSIsIDM1MCwgYXMuUE9TSVhjdCgiMjAxNy0wMS0wNyAxMzowMDowMCIpLAogICJCIiwgMjAwLCBhcy5QT1NJWGN0KCIyMDE3LTAxLTA5IDIzOjAwOjAwIiksCiAgIkMiLCAxNTAsIGFzLlBPU0lYY3QoIjIwMTctMDEtMDggMTM6MDA6MDAiKSwKICAiRCIsIDYyNSwgYXMuUE9TSVhjdCgiMjAxNy0wMS0xMiAwNzowMDowMCIpLAogICJFIiwgNzUwLCBhcy5QT1NJWGN0KCIyMDE3LTAxLTEwIDAyOjAwOjAwIikKICAKKQoKbGlicmFyeShzaGFkb3d0ZXh0KQpwbG90MThrIDwtIGRhdGFCaW5uZWRfMDEgJT4lIGZpbHRlcihmcmVxdWVuY3kgPT0gMTgwMDApICU+JSBnZ3Bsb3QoYWVzKHggPSB0aW1lTWV4LCB5ID0gZGVwdGhfYmluLCBmaWxsID0gdmFsdWUpKSArIGdlb21fdGlsZSgpICsgc2NhbGVfeV9yZXZlcnNlKCkgKyBzY2FsZV9maWxsX3ZpcmlkaXNfYyhsaW1pdHMgPSBjKC0xNjUsIC03NSksIG9vYiA9IHNjYWxlczo6c3F1aXNoKSArCiAgc2NhbGVfeF9kYXRldGltZShicmVha3MgPSB0aW1lQnJlYWtzLCBkYXRlX2xhYmVscyA9ICIlZDo6JUgiKSArIGxhYnMoeCA9ICJkYXk6OmhvdXIiLCB5ID0gImRlcHRoIChtKSIsIGZpbGwgPSAiYmFja3NjYXR0ZXIgKGRCKSIpICsgdGhlbWVfYncoKSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHZqdXN0ID0gMC41KSkgKyBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAxNjAsIGNvbG9yID0gImRhcmtncmVlbiIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSA4NTAsIGNvbG9yID0gImRhcmtibHVlIikgKwogIGdlb21fc2hhZG93dGV4dChkYXRhID0gcGxvdExldHRlcnMsIGFlcyh4ID0gdGltZU1leCAtIDEyICogNjBeMiwgeSA9IGRlcHRoX2JpbiwgbGFiZWwgPSBsZXR0ZXIpLCAgaW5oZXJpdC5hZXMgPSBGQUxTRSwgc2l6ZSA9IDYsIGJnLmNvbG9yID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siKSArCiAgZ2VvbV9zZWdtZW50KGRhdGEgPSBwbG90TGV0dGVycywgaW5oZXJpdC5hZXMgPSBGQUxTRSwgYWVzKHggPSB0aW1lTWV4IC0gOSAqIDYwXjIsIHhlbmQgPSB0aW1lTWV4LCB5ID0gZGVwdGhfYmluLCB5ZW5kID0gZGVwdGhfYmluKSwgYXJyb3cgPSBhcnJvdyhsZW5ndGggPSB1bml0KDAuMDMsICJucGMiKSksIGNvbG9yID0gIndoaXRlIiwgc2l6ZSA9IDEuNSkgKyAKICBnZW9tX3NlZ21lbnQoZGF0YSA9IHBsb3RMZXR0ZXJzLCBpbmhlcml0LmFlcyA9IEZBTFNFLCBhZXMoeCA9IHRpbWVNZXggLSA5ICogNjBeMiwgeGVuZCA9IHRpbWVNZXgsIHkgPSBkZXB0aF9iaW4sIHllbmQgPSBkZXB0aF9iaW4pLCBhcnJvdyA9IGFycm93KGxlbmd0aCA9IHVuaXQoMC4wMywgIm5wYyIpKSkKcGxvdDE4awoKI2dnc2F2ZSgiZmlndXJlcy9zdGF0aW9uUDJfRUs2MF8xOGtPbmx5LnBuZyIpCmBgYAoKYGBge3J9CnBsb3RMZXR0ZXJzIDwtIHRyaWJibGUoCiAgfmxldHRlciwgfmRlcHRoX2JpbiwgfnRpbWVNZXgsCiAgIkEiLCAzMDAsIGFzLlBPU0lYY3QoIjIwMTctMDEtMDcgMTM6MDA6MDAiKSwKICAiQiIsIDIwMCwgYXMuUE9TSVhjdCgiMjAxNy0wMS0wOSAyMzowMDowMCIpLAogICJDIiwgMTUwLCBhcy5QT1NJWGN0KCIyMDE3LTAxLTA4IDEzOjAwOjAwIiksCiAgIkQiLCA2MjUsIGFzLlBPU0lYY3QoIjIwMTctMDEtMTIgMDc6MDA6MDAiKSwKICAiRSIsIDc1MCwgYXMuUE9TSVhjdCgiMjAxNy0wMS0xMCAwMjowMDowMCIpCiAgCikKCmxpYnJhcnkoc2hhZG93dGV4dCkKcGxvdDM4ayA8LSBkYXRhQmlubmVkXzAxICU+JSBmaWx0ZXIoZnJlcXVlbmN5ID09IDM4MDAwKSAlPiUgZ2dwbG90KGFlcyh4ID0gdGltZU1leCwgeSA9IGRlcHRoX2JpbiwgZmlsbCA9IHZhbHVlKSkgKyBnZW9tX3RpbGUoKSArIHNjYWxlX3lfcmV2ZXJzZSgpICsgc2NhbGVfZmlsbF92aXJpZGlzX2MobGltaXRzID0gYygtMTY1LCAtOTUpLCBvb2IgPSBzY2FsZXM6OnNxdWlzaCkgKwogIHNjYWxlX3hfZGF0ZXRpbWUoYnJlYWtzID0gdGltZUJyZWFrcywgZGF0ZV9sYWJlbHMgPSAiJWQ6OiVIIikgKyBsYWJzKHggPSAiRGF5OjpIb3VyIiwgeSA9ICJEZXB0aCAobSkiLCBmaWxsID0gIkJhY2tzY2F0dGVyIChkQikiKSArIHRoZW1lX2J3KCkgICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMTYwLCBjb2xvciA9ICJkYXJrZ3JlZW4iKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gODUwLCBjb2xvciA9ICJkYXJrYmx1ZSIpICsKICBnZW9tX3NoYWRvd3RleHQoZGF0YSA9IHBsb3RMZXR0ZXJzWzE6MixdLCBhZXMoeCA9IHRpbWVNZXggLSAxMiAqIDYwXjIsIHkgPSBkZXB0aF9iaW4sIGxhYmVsID0gbGV0dGVyKSwgIGluaGVyaXQuYWVzID0gRkFMU0UsIHNpemUgPSA2LCBiZy5jb2xvciA9ICJ3aGl0ZSIsIGNvbG9yID0gImJsYWNrIikgKwogIGdlb21fc2VnbWVudChkYXRhID0gcGxvdExldHRlcnNbMToyLF0sIGluaGVyaXQuYWVzID0gRkFMU0UsIGFlcyh4ID0gdGltZU1leCAtIDkgKiA2MF4yLCB4ZW5kID0gdGltZU1leCwgeSA9IGRlcHRoX2JpbiwgeWVuZCA9IGRlcHRoX2JpbiksIGFycm93ID0gYXJyb3cobGVuZ3RoID0gdW5pdCgwLjAzLCAibnBjIikpLCBjb2xvciA9ICJ3aGl0ZSIsIHNpemUgPSAxLjUpICsgCiAgZ2VvbV9zZWdtZW50KGRhdGEgPSBwbG90TGV0dGVyc1sxOjIsXSwgaW5oZXJpdC5hZXMgPSBGQUxTRSwgYWVzKHggPSB0aW1lTWV4IC0gOSAqIDYwXjIsIHhlbmQgPSB0aW1lTWV4LCB5ID0gZGVwdGhfYmluLCB5ZW5kID0gZGVwdGhfYmluKSwgYXJyb3cgPSBhcnJvdyhsZW5ndGggPSB1bml0KDAuMDMsICJucGMiKSkpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUpLAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpCiAgICAgICAgKQpwbG90MzhrCgpnZ3NhdmUoImZpZ3VyZXMvc3RhdGlvblAyX0VLNjBfMzhrT25seS5wbmciKQpgYGAKCgpgYGB7cn0KcGxvdDE4ayArIHNjYWxlX3lfcmV2ZXJzZShsaW1pdHMgPSBjKDUwMCwgMjAwKSkKYGBgCgpgYGB7cn0KcGxvdDIwMGsgPC0gZGF0YUJpbm5lZF8wMSAlPiUgZmlsdGVyKGZyZXF1ZW5jeSA9PSAyMDAwMDApICU+JSBnZ3Bsb3QoYWVzKHggPSB0aW1lTWV4LCB5ID0gZGVwdGhfYmluLCBmaWxsID0gdmFsdWUpKSArIGdlb21fdGlsZSgpICsgc2NhbGVfeV9yZXZlcnNlKCkgKyBzY2FsZV9maWxsX3ZpcmlkaXNfYyhsaW1pdHMgPSBjKC0xNjUsIC0xNTUpLCBvb2IgPSBzY2FsZXM6OnNxdWlzaCkgKwogIHNjYWxlX3hfZGF0ZXRpbWUoYnJlYWtzID0gdGltZUJyZWFrcywgZGF0ZV9sYWJlbHMgPSAiJWQ6OiVIIikgKyBsYWJzKHggPSAiZGF5Ojpob3VyIiwgeSA9ICJkZXB0aCAobSkiLCBmaWxsID0gImJhY2tzY2F0dGVyIChkQikiKSArIHRoZW1lX2J3KCkgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSkpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMTYwLCBjb2xvciA9ICJkYXJrZ3JlZW4iKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gODUwLCBjb2xvciA9ICJkYXJrYmx1ZSIpCnBsb3QyMDBrCmBgYAoKYGBge3IgZmlnLmhlaWdodD0yMCwgZmlnLndpZHRoID0gOH0KZGF0YUJpbm5lZF8wMSAlPiUgZ2dwbG90KGFlcyh4ID0gdGltZU1leCwgeSA9IGRlcHRoX2JpbiwgZmlsbCA9IHZhbHVlKSkgKyBnZW9tX3RpbGUoKSArIHNjYWxlX3lfcmV2ZXJzZSgpICsgc2NhbGVfZmlsbF92aXJpZGlzX2MobGltaXRzID0gYygtMTY1LCAtNzUpLCBvb2IgPSBzY2FsZXM6OnNxdWlzaCkgKwogIHNjYWxlX3hfZGF0ZXRpbWUoYnJlYWtzID0gdGltZUJyZWFrcywgZGF0ZV9sYWJlbHMgPSAiJWQ6OiVIIikgKyBsYWJzKHggPSAiZGF5Ojpob3VyIiwgeSA9ICJEZXB0aCAobSkiLCBmaWxsID0gImJhY2tzY2F0dGVyIChkQikiKSArIHRoZW1lX2J3KCkgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSkpICsKICAKICAKICBmYWNldF93cmFwKH5mcmVxdWVuY3ksIG5jb2wgPSAxKQoKI2dnc2F2ZSgiZmlndXJlcy9zdGF0aW9uUDJfRUs2MF9nbzcuc3ZnIiwgd2lkdGggPSA0LCBoZWlnaHQgPSAxMCkKZ2dzYXZlKCJmaWd1cmVzL3N0YXRpb25QMl9FSzYwX2dvNy5wbmciLCB3aWR0aCA9IDYsIGhlaWdodCA9IDEwKQpgYGA=